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

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

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

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

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

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

    DynamicFactory.h文件


 
 
  1. #ifndef __DYNAMIC_FACTORY_H__
  2. #define __DYNAMIC_FACTORY_H__
  3. #ifdef __GNUC__
  4. #include <cxxabi.h>
  5. #endif
  6. #include <assert.h>
  7. #include <string.h>
  8. #include <stdlib.h>
  9. #include <map>
  10. #include <string>
  11. #include <typeinfo>
  12. // 动态对象基类
  13. class DynamicObject
  14. {
  15. public:
  16. DynamicObject() {}
  17. virtual ~DynamicObject() {}
  18. };
  19. // 动态对象创建工厂
  20. class DynamicFactory
  21. {
  22. public:
  23. typedef DynamicObject* (*CreateFunction)();
  24. static DynamicFactory & Instance()
  25. {
  26. static DynamicFactory fac;
  27. return fac;
  28. }
  29. // 解析类型名称(转换为 A::B::C 的形式)
  30. static std:: string ReadTypeName(const char * name)
  31. {
  32. // 这里省略,具体代码在最后给出
  33. ...
  34. }
  35. bool Regist(const char * name, CreateFunction func)
  36. {
  37. if (!func)
  38. {
  39. return false;
  40. }
  41. std:: string type_name = ReadTypeName(name);
  42. return _create_function_map.insert( std::make_pair(type_name, func)).second;
  43. }
  44. DynamicObject * Create(const std::string & type_name)
  45. {
  46. if (type_name.empty())
  47. {
  48. return NULL;
  49. }
  50. std:: map< std:: string, CreateFunction>::iterator it = _create_function_map.find(type_name);
  51. if (it == _create_function_map.end())
  52. {
  53. return NULL;
  54. }
  55. return it->second();
  56. }
  57. template< typename T>
  58. T * Create(const std::string & type_name)
  59. {
  60. DynamicObject * obj = Create(type_name);
  61. if (!obj)
  62. {
  63. return NULL;
  64. }
  65. T * real_obj = dynamic_cast<T*>(obj);
  66. if (!real_obj)
  67. {
  68. delete obj;
  69. return NULL;
  70. }
  71. return real_obj;
  72. }
  73. public:
  74. std:: map< std:: string, CreateFunction> _create_function_map;
  75. };
  76. // 动态对象创建器
  77. template< typename T>
  78. class DynamicCreate : public DynamicObject
  79. {
  80. public:
  81. static DynamicObject * CreateObject()
  82. {
  83. return new T();
  84. }
  85. struct Registor
  86. {
  87. Registor()
  88. {
  89. if (!DynamicFactory::Instance().Regist( typeid(T).name(), CreateObject))
  90. {
  91. assert( false);
  92. }
  93. }
  94. inline void do_nothing()const { }
  95. };
  96. static Registor s_registor;
  97. public:
  98. DynamicCreate()
  99. {
  100. s_registor.do_nothing();
  101. }
  102. virtual ~DynamicCreate()
  103. {
  104. s_registor.do_nothing();
  105. }
  106. };
  107. template < typename T>
  108. typename DynamicCreate<T>::Registor DynamicCreate<T>::s_registor;
  109. #endif

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

    测试代码mian.cpp


 
 
  1. #include <stdio.h>
  2. #include "DynamicFactory.h"
  3. class Test1 : public DynamicCreate<Test1>
  4. {
  5. public:
  6. // 注意:使用gcc,一定要显示申明构造函数,否则不会执行注册代码
  7. Test1() {}
  8. };
  9. namespace OK {
  10. struct Test2 : public DynamicCreate<Test2>
  11. {
  12. Test2() {}
  13. class Test3 : public DynamicCreate<Test3>
  14. {
  15. public:
  16. Test3() {}
  17. };
  18. };
  19. struct Test4 : public DynamicCreate<Test4>
  20. {
  21. Test4() {}
  22. };
  23. }
  24. using namespace OK;
  25. //测试代码
  26. int main()
  27. {
  28. Test1 * p1 = DynamicFactory::Instance().Create<Test1>( "Test1");
  29. printf( "Create Test1 %s\n", (p1 ? "success" : "failure"));
  30. OK::Test2 * p2 = DynamicFactory::Instance().Create<OK::Test2>( "OK::Test2");
  31. printf( "Create OK::Test2 %s\n", (p2 ? "success" : "failure"));
  32. OK::Test2::Test3 * p3 = DynamicFactory::Instance().Create<OK::Test2::Test3>( "OK::Test2::Test3");
  33. printf( "Create OK::Test2::Test3 %s\n", (p3 ? "success" : "failure"));
  34. OK::Test4 * p4 = DynamicFactory::Instance().Create<OK::Test4>( "OK::Test4");
  35. printf( "Create OK::Test4 %s\n", (p4 ? "success" : "failure"));
  36. return 0;
  37. }

  输出:

[programmer@localhost test]$ ./test
Create Test1 success
Create OK::Test2 success
Create OK::Test2::Test3 success
Create OK::Test4 success

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


 
 
  1. // 解析类型名称(转换为 A::B::C 的形式)
  2. // GCC 的type_info::name()输出的名称很猥琐,这里只做简单的解析,只支持自定义的结构体(非模板),类(非模板)、枚举、联合
  3. static std:: string ReadTypeName(const char * name)
  4. {
  5. #ifndef __GNUC__
  6. const char * p = strstr(name, " ");
  7. if (p)
  8. {
  9. size_t prev_len = ( size_t)(p - name);
  10. if ( memcmp(name, "class", prev_len) == 0 ||
  11. memcmp(name, "struct", prev_len) == 0 ||
  12. memcmp(name, "enum", prev_len) == 0 ||
  13. memcmp(name, "union", prev_len) == 0)
  14. {
  15. p += 1;
  16. return std:: string(p);
  17. }
  18. }
  19. return std:: string(name);
  20. #else
  21. char * real_name = abi::__cxa_demangle(name, nullptr, nullptr, nullptr);
  22.      std:: string real_name_string(real_name);
  23.      free(real_name);
  24.      return real_name_string;
  25. #endif
  26. }




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值