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

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

  输出:

  1. [programmer@localhost test]$ ./test  
  2. Create Test1 success  
  3. Create OK::Test2 success  
  4. Create OK::Test2::Test3 success  
  5. 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函数代码

  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.   
  20.         return std::string(name);  
  21. #else  
  22.         char * real_name = abi::__cxa_demangle(name, nullptr, nullptr, nullptr);  
  23.              std::string real_name_string(real_name);  
  24.              free(real_name);  
  25.              return real_name_string;  
  26. #endif  
  27.     }  
// 解析类型名称(转换为 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
	}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值