有时候我们希望通过一个字符串创建类,可以通过if..else...来实现 string str = "some_class_name"; 如 ------------------------------------------------------------ if(str==string("class1")){ class1 xx; xx.do(); } else(str ==string("class2")){ class 2 xx2; xx2.do(); } else{ } ------------------------------------------------------------ 上面代码不仅丑陋,而且难以扩展,如果我们希望用一个统一的基类来调用函数,如 ------------------------------------------------------------ string str = "some_class_name"; Base* s = create_class(str); if(s!=NULL) s->do(); ------------------------------------------------------------ 上面的代码就整齐多了,而且以后增加新的类,也不需要修改调用的地方。 同时,如果我们定义的这个Base* create_class(string name)函数能自动帮我们检查有没有一个类名符合输入的字符串,那就完美了。 我们很容易想到,如果有一个全局的map<string, CBase* Create()>来帮我们保存,类名字符串与对应类的新建函数, 输入字符串,通过map找到每个类都有的重载函数CBase* Create() 就可以返回需要的类了。 假设class CBase; class CDerived: CBase; 但是,CBase* Create()怎么新建所需要的类呢,可以用下面这个代码,在执行的时候new一个, 这通过重载很容易实现 static CBase *Create() { return new CDerived; } 剩下的问题就是怎么往map里注册这个我们的CBase 和 CDerived了:可以通过类中声明一个辅助类,在辅助类中的构造函数中,插入我们的类名,然后在外类中声明一个static的辅助类,就完成了注册! 上述的代码都可以通过宏展开来完成。 实现代码如下, ------------------------------------------------------------ #include <string> #include <map> #include <iostream> using namespace std; // 声明具有动态创建的基类 #define DECLEAR_DYNCRT_BASE(CBase) \ public: \ typedef CBase *(*ClassGen)(); /* 声明函数指针*/ \ static CBase *Create(const string &class_name) /* 工厂函数 */ \ { \ std::map<string, ClassGen>::iterator iter = m_class_set.find(class_name); \ if (m_class_set.end() != iter) \ { \ return ((*iter).second)(); \ } \ return NULL; \ } \ protected: \ static void Register(const string &class_name, ClassGen class_gen) /* 注册函数 */ \ { \ m_class_set.insert(map<string, ClassGen>::value_type(class_name, class_gen)); \ } \ static std::map<string, ClassGen> m_class_set; /* 存储子类信息 */ // 用于实现基类 #define IMPLEMENT_DYNCRT_BASE(CBase) \ std::map<string, CBase::ClassGen> CBase::m_class_set; ------------------------------------------------------------ // 用于声明一个能够被动态创建的类(用一个全局对象进行注册) #define DECLEAR_DYNCRT_CLASS(CDerived, CBase) \ public: \ struct CDerived##Register /* 辅助类,用于注册 */ \ { \ CDerived##Register() \ { \ static bool bRegistered = false; /* 注册子类,保证唯一注册一次 */ \ if(!bRegistered) \ { \ CBase::Register(#CDerived, CDerived::Create); /* 注册子类信息 */ \ bRegistered = true; \ } \ } \ } ; \ static CBase *Create() /* 工厂函数 */ \ { \ return new CDerived; \ } \ static struct CDerived##Register m_t##CDerived##Register; // 用于实现一个能被动态创建的类 #define IMPLEMENT_DYNCRT_CLASS(CDerived) \ static CDerived::CDerived##Register m_t##CDerived##Register; ------------------------------------------------------------ // 声明基类: class CBase { DECLEAR_DYNCRT_BASE(CBase) DECLEAR_DYNCRT_CLASS(CBase, CBase) public: virtual void Print() { std::cout << "This is base!" << std::endl; } }; IMPLEMENT_DYNCRT_BASE(CBase) IMPLEMENT_DYNCRT_CLASS(CBase) ------------------------------------------------------------ //声明继承类 class CDerived : public CBase { DECLEAR_DYNCRT_CLASS(CDerived, CBase) public: virtual void Print() { cout << "This is derived!" << endl; } }; IMPLEMENT_DYNCRT_CLASS(CDerived) //声明再继承类 class ExCDerived : public CDerived { DECLEAR_DYNCRT_CLASS(ExCDerived, CBase) public: virtual void Print() { cout << "This is ExCDerived!" << endl; } }; IMPLEMENT_DYNCRT_CLASS(ExCDerived) int main() { CBase* base = CBase::Create("CBase"); if (base) { base->Print(); } CBase* base2 = CBase::Create("CDerived"); if (base2) { base2->Print(); } CBase* base3 = CBase::Create("ExCDerived"); if (base3) { base3->Print(); } return 0; } ———————————————— 版权声明:本文为CSDN博主「sun6623518」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/sun6623518/article/details/11391861 |
|