分享

C++运行时通过字符串动态创建类

 星光闪亮图书馆 2020-04-14

有时候我们希望通过一个字符串创建类,可以通过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

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多