三十一、反射、C++动态对象创建实现

一、反射          

          反射是指计算机程序运行时Run time)可以访问、检测和修改它本身状态或行为的一种能力。用比喻来说,那种程序能够“观察”并且修改自己的行为。它包括动态获取类型信息(包括方法和属性),动态创建对象,动态获取对象的方法,动态操作对象的属性。为了实现反射,必须给每个类添加元数据。这里我们只实现动态创建对象。

二、动态对象的创建

          首先,我们首先想到是通过new "Circle"这样的方式创建,但是这在C++里面明显是行不通的。我们换一种方式,增加一个间接层,用一个工厂类负责对象的创建。我们传入一个字符串,工厂类返回这个字符串对应的对象。

Circle *p = DynObjectFactory::CreateObject("Circle")

为了让这个工厂能根据字符串创建对应对象,我们肯定需要在工厂里保存类字符串和对应创建对象的方法信息。这时我们可以定义一个map容器,把字符串作为key创建对象的方法作为value,因为我们并不知道要创建什么类型的对象,我们可以用void*指针作为创建方法的返回值。

typedef void* (*CREATE_FUNC)();
class DynObjectFactory
{
public:
	static void* CreateObject(const string& name_)
	{
		map<string,CREATE_FUNC>::const_iterator it;
		it = mapCls_.find(name_);
		if (it != mapCls_.end())
			return it->second(); //调用second函数
		else
			return 0;
	}
private:
	static map<string,CREATE_FUNC> mapCls_;
};
然后,我们希望我们自己的对象能注册到map中,我们可以给DynObjectFactory增加一个注册方法:

typedef void* (*CREATE_FUNC)();
class DynObjectFactory
{
public:
	static void* CreateObject(const string& name_)
	{
		map<string,CREATE_FUNC>::const_iterator it;
		it = mapCls_.find(name_);
		if (it != mapCls_.end())
			return it->second(); //调用second函数
		else
			return 0;
	}
	static void Register(const string& name_,CREATE_FUNC func_)
	{
		mapCls_.insert(make_pair(name_,func_));
	}
private:
	static map<string,CREATE_FUNC> mapCls_;
};

现在这个工厂类已经可以使用了,但是对于每一个类我们都需要调用Register手动注册到工厂,然后才能让工厂动态创建。这显然不够简洁。我们可以在定义一个Register类帮我们完成对象的注册:

class Register
{
public:
	Register(const string& name_,CREATE_FUNC func_)
	{
		DynObjectFactory::Register(name_,func_);
	}
};
为了能让我们自定义的类能自动调用Register类注册到工厂中,还需要定义一个宏:

#define REGISTER_CLASS(class_name)\
class class_name##Register \
{\
public:\
	static void* NewIntance()\
	{\
		return new class_name;\
	}\
private:\
	static Register reg;\
};\
Register class_name##Register::reg(#class_name,class_name##Register::NewIntance);
在我们需要注册类的cpp文件里我们可以加上这个宏完成自动注册:

REGISTER_CLASS(Circle)
        到这里,动态创建对象的功能已经完成了。但是它是如何工作的呢?

首先,在预处理期间,我们加入的宏REGISTER_CLASS(Circle)被展开为一个CircleRegister的类,这个类包含了Circle的创建方法和一个静态的注册方法对象。因为静态类型先于一切对象被初始化,所以在我们的对象创建之前,会初始化这个静态对象完成对象创建方法的注册。注册完成之后,我们就可以根据类字符串创建我们需要的对象:

Circle *p = DynObjectFactory::CreateObject("Circle")



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值