C++实现反射(根据类名动态创建对象)

xiaoxiao2021-02-28  10

 和网上大多数实现一样,这里也是采用工厂方法来实现对象的动态创建。大致原理为,创建一个单例工厂类,其中维护一个map(类名->对象创建函数)。创建对象时,传入类名,然后根据此类名查询出创建函数,最后创建对象。

    采用这种方式,有一个关键问题,便是在工厂中注册类名。我们的办法是针对于每一个类(Class),定义一个注册类(ClassReg),在注册类(ClassReg)的构造函数中注册此类(Class),然后再定义一个注册类的全局对象,在该全局对象初始化时,便会执行注册代码完成注册。

    看到到这里懒人不乐意了,难道我们每写一个类,还要写一个相应的注册类?于是有人提出了使用宏来替换相应的代码,这样便大大减少了重复代码量。

    采用宏当然可以,但是只能满足部分懒人。还有一部分人更懒,他们连使用这个宏完成注册都不想干,是呀,每写完一个类,还要在类后面使用宏来注册,这样确实还是比较麻烦。而且这样代码不够美观,也不便于维护,同时采用宏来转换类名,遇到命名空间,嵌套类,会非常麻烦,我们必须在注册的时候,把名字写全,比如REG_CLASS(MyNameSpace::MyClass::MyStruct)。

    那么有没有更好的方法呢?当然有,我们可以用类模板来实现这种功能。设想这种方式,若我们要定义一个类MyClass,并且想让此类支持动态创建,那么我们只需这样定义即可class MyClass : public DynamicCreate<MyClass>{};。这样是不是清晰多了?下面请看代码:

    DynamicFactory.h文件

[cpp] view plain copy print ? #ifndef __DYNAMIC_FACTORY_H__  #define __DYNAMIC_FACTORY_H__    #ifdef __GNUC__  #include <cxxabi.h>  #endif    #include <assert.h>  #include <string.h>  #include <stdlib.h>  #include <map>  #include <string>  #include <typeinfo>    // 动态对象基类  class DynamicObject  {  public:      DynamicObject() {}      virtual ~DynamicObject() {}  };    // 动态对象创建工厂  class DynamicFactory  {  public:        typedef DynamicObject* (*CreateFunction)();        static DynamicFactory & Instance()      {          static DynamicFactory fac;          return fac;      }        // 解析类型名称(转换为 A::B::C 的形式)      static std::string ReadTypeName(const char * name)      {                   // 这里省略,具体代码在最后给出                   ...      }        bool Regist(const char * name, CreateFunction func)      {          if (!func)          {              return false;          }          std::string type_name = ReadTypeName(name);          return _create_function_map.insert(std::make_pair(type_name, func)).second;      }        DynamicObject * Create(const std::string & type_name)      {          if (type_name.empty())          {              return NULL;          }            std::map<std::string, CreateFunction>::iterator it = _create_function_map.find(type_name);          if (it == _create_function_map.end())          {              return NULL;          }            return it->second();      }        template<typename T>      T * Create(const std::string & type_name)      {          DynamicObject * obj = Create(type_name);          if (!obj)          {              return NULL;          }          T * real_obj = dynamic_cast<T*>(obj);          if (!real_obj)          {              delete obj;              return NULL;          }          return real_obj;      }    public:        std::map<std::string, CreateFunction> _create_function_map;  };    // 动态对象创建器  template<typename T>  class DynamicCreate : public DynamicObject  {  public:      static DynamicObject * CreateObject()      {          return new T();      }        struct Registor      {          Registor()          {              if (!DynamicFactory::Instance().Regist(typeid(T).name(), CreateObject))              {                  assert(false);              }          }            inline void do_nothing()const { }      };        static Registor s_registor;    public:      DynamicCreate()      {          s_registor.do_nothing();      }        virtual ~DynamicCreate()      {          s_registor.do_nothing();      }  };    template <typename T>  typename DynamicCreate<T>::Registor DynamicCreate<T>::s_registor;    #endif   #ifndef __DYNAMIC_FACTORY_H__ #define __DYNAMIC_FACTORY_H__ #ifdef __GNUC__ #include <cxxabi.h> #endif #include <assert.h> #include <string.h> #include <stdlib.h> #include <map> #include <string> #include <typeinfo> // 动态对象基类 class DynamicObject { public: DynamicObject() {} virtual ~DynamicObject() {} }; // 动态对象创建工厂 class DynamicFactory { public: typedef DynamicObject* (*CreateFunction)(); static DynamicFactory & Instance() { static DynamicFactory fac; return fac; } // 解析类型名称(转换为 A::B::C 的形式) static std::string ReadTypeName(const char * name) { // 这里省略,具体代码在最后给出 ... } bool Regist(const char * name, CreateFunction func) { if (!func) { return false; } std::string type_name = ReadTypeName(name); return _create_function_map.insert(std::make_pair(type_name, func)).second; } DynamicObject * Create(const std::string & type_name) { if (type_name.empty()) { return NULL; } std::map<std::string, CreateFunction>::iterator it = _create_function_map.find(type_name); if (it == _create_function_map.end()) { return NULL; } return it->second(); } template<typename T> T * Create(const std::string & type_name) { DynamicObject * obj = Create(type_name); if (!obj) { return NULL; } T * real_obj = dynamic_cast<T*>(obj); if (!real_obj) { delete obj; return NULL; } return real_obj; } public: std::map<std::string, CreateFunction> _create_function_map; }; // 动态对象创建器 template<typename T> class DynamicCreate : public DynamicObject { public: static DynamicObject * CreateObject() { return new T(); } struct Registor { Registor() { if (!DynamicFactory::Instance().Regist(typeid(T).name(), CreateObject)) { assert(false); } } inline void do_nothing()const { } }; static Registor s_registor; public: DynamicCreate() { s_registor.do_nothing(); } virtual ~DynamicCreate() { s_registor.do_nothing(); } }; template <typename T> typename DynamicCreate<T>::Registor DynamicCreate<T>::s_registor; #endif

    代码不多,就不做解释了。

    测试代码mian.cpp

[cpp] view plain copy print ? #include <stdio.h>  #include "DynamicFactory.h"    class Test1 : public DynamicCreate<Test1>  {  public:      // 注意:使用gcc,一定要显示申明构造函数,否则不会执行注册代码      Test1() {}  };    namespace OK {      struct Test2 : public DynamicCreate<Test2>      {          Test2() {}            class Test3 : public DynamicCreate<Test3>          {          public:              Test3() {}          };      };        struct Test4 : public DynamicCreate<Test4>      {          Test4() {}      };  }    using namespace OK;    //测试代码  int main()  {      Test1 * p1 = DynamicFactory::Instance().Create<Test1>("Test1");      printf("Create Test1 %s\n", (p1 ? "success" : "failure"));        OK::Test2 * p2 = DynamicFactory::Instance().Create<OK::Test2>("OK::Test2");      printf("Create OK::Test2 %s\n", (p2 ? "success" : "failure"));        OK::Test2::Test3 * p3 = DynamicFactory::Instance().Create<OK::Test2::Test3>("OK::Test2::Test3");      printf("Create OK::Test2::Test3 %s\n", (p3 ? "success" : "failure"));        OK::Test4 * p4 = DynamicFactory::Instance().Create<OK::Test4>("OK::Test4");      printf("Create OK::Test4 %s\n", (p4 ? "success" : "failure"));        return 0;  }   #include <stdio.h> #include "DynamicFactory.h" class Test1 : public DynamicCreate<Test1> { public: // 注意:使用gcc,一定要显示申明构造函数,否则不会执行注册代码 Test1() {} }; namespace OK { struct Test2 : public DynamicCreate<Test2> { Test2() {} class Test3 : public DynamicCreate<Test3> { public: Test3() {} }; }; struct Test4 : public DynamicCreate<Test4> { Test4() {} }; } using namespace OK; //测试代码 int main() { Test1 * p1 = DynamicFactory::Instance().Create<Test1>("Test1"); printf("Create Test1 %s\n", (p1 ? "success" : "failure")); OK::Test2 * p2 = DynamicFactory::Instance().Create<OK::Test2>("OK::Test2"); printf("Create OK::Test2 %s\n", (p2 ? "success" : "failure")); OK::Test2::Test3 * p3 = DynamicFactory::Instance().Create<OK::Test2::Test3>("OK::Test2::Test3"); printf("Create OK::Test2::Test3 %s\n", (p3 ? "success" : "failure")); OK::Test4 * p4 = DynamicFactory::Instance().Create<OK::Test4>("OK::Test4"); printf("Create OK::Test4 %s\n", (p4 ? "success" : "failure")); return 0; }   输出:

[plain] view plain copy print ? [programmer@localhost test]$ ./test  Create Test1 success  Create OK::Test2 success  Create OK::Test2::Test3 success  Create OK::Test4 success   [programmer@localhost test]$ ./test Create Test1 success Create OK::Test2 success Create OK::Test2::Test3 success Create OK::Test4 success

  下面给出上面省略的 ReadTypeName函数代码

[cpp] view plain copy print ? // 解析类型名称(转换为 A::B::C 的形式)      // GCC 的type_info::name()输出的名称很猥琐,这里只做简单的解析,只支持自定义的结构体(非模板),类(非模板)、枚举、联合      static std::string ReadTypeName(const char * name)      {  #ifndef __GNUC__          const char * p = strstr(name, " ");          if (p)          {              size_t prev_len = (size_t)(p - name);              if (memcmp(name, "class", prev_len) == 0 ||                  memcmp(name, "struct", prev_len) == 0 ||                  memcmp(name, "enum", prev_len) == 0 ||                  memcmp(name, "union", prev_len) == 0)              {                  p += 1;                  return std::string(p);              }          }            return std::string(name);  #else          char * real_name = abi::__cxa_demangle(name, nullptr, nullptr, nullptr);               std::string real_name_string(real_name);               free(real_name);               return real_name_string;  #endif      }   // 解析类型名称(转换为 A::B::C 的形式) // GCC 的type_info::name()输出的名称很猥琐,这里只做简单的解析,只支持自定义的结构体(非模板),类(非模板)、枚举、联合 static std::string ReadTypeName(const char * name) { #ifndef __GNUC__ const char * p = strstr(name, " "); if (p) { size_t prev_len = (size_t)(p - name); if (memcmp(name, "class", prev_len) == 0 || memcmp(name, "struct", prev_len) == 0 || memcmp(name, "enum", prev_len) == 0 || memcmp(name, "union", prev_len) == 0) { p += 1; return std::string(p); } } return std::string(name); #else char * real_name = abi::__cxa_demangle(name, nullptr, nullptr, nullptr);      std::string real_name_string(real_name);      free(real_name);      return real_name_string; #endif }
转载请注明原文地址: https://www.6miu.com/read-2350078.html

最新回复(0)