由于前不久须要作一个合并多个项目代码,因此须要经过配置文件来控制建立对象,百度用字符串建立对象,搜索半天无果,后来翻看大话设计模式的时候在工厂模式看到一个反射机制,即经过类名建立对象,因此搜索了一下,果真可以找到,因此下载之后分析了哈,进行本身需求进行修改,现整理一下。使用qt5.5.1进行编码。设计模式
一、定义一个回调函数,用来建立这个类的实例;定义一个哈希,用于保存类名和建立实例的回调函数;编辑器
二、设计一个单例,用于管理哈希。(可用静态成员变量替换);函数
三、设计一个工厂类,。经过类工厂来动态建立类对象和注册类;测试
四、建立注册类,将回调函数存入哈希里面,类名字作为map的key值;编码
五、定义须要建立对象的类,用于测试。.net
首先声明一个回调函数设计
typedef void* (*fun_ptr)();指针
声明一个哈希:对象
typedef std::map<const QString, fun_ptr> create_obj_map; //用来保存回调函数指针,经过registClass()函数来实现类名和函数的插入。blog
定义一个单例,用于处理哈希,也能够定义成一个静态成员变量,可是以前试过几回,没成功,先使用单例吧。
class LazySingleton
{
public:
template<class T>
static T& instance()
{
static T _instance;
return _instance;
}
};
定义一个工厂类,用于经过此获取哈希,方法registerClass用于插入类名和建立此类的方法,getInstance函数返回哈希中经过回调函数建立的类的实例化,参数为传入的类名。
class ClassFactory
{
public:
static void *getInstance(const QString &className);
static void registerClass(const QString &className, fun_ptr fp);
};
void *ClassFactory::getInstance(const QString &className)
{
std::cout << LazySingleton::instance<create_obj_map>().size() << std::endl;
create_obj_map::iterator iter = LazySingleton::instance<create_obj_map>().begin();
create_obj_map::iterator iterEnd = LazySingleton::instance<create_obj_map>().end();
while (iter != iterEnd)
{
if (iter->first == className)
{
return iter->second();
}
iter++;
}
return NULL;
}
void ClassFactory::registerClass(const QString &className, fun_ptr fp)
{
LazySingleton::instance<create_obj_map>().insert(std::make_pair(className, fp));
}
这样,咱们的单例工厂类就设计完成了。
下面咱们须要设计一个用来动态建立类的类,被建立的类经过本类来向类工厂注册对象的函数。
class Register
{
public:
Register(const char* className, fun_ptr fp);
};
Register::Register(const char* className, fun_ptr fp)
{
ClassFactory::registerClass(className, fp);
}
该类设计了个宏,用于实现动态建立,后面的类中会用到。
该宏主要为了实现两个功能,一个是配合类工厂来建立一个新的类,新的类用于建立传入的类,一个是将新的类的建立对象的方法注册到哈希中。
下面先帖代码:
#define REGISTER(ClassName) \
class Register##ClassName \
{ \
public: \
static void* instance() \
{ \
return new ClassName; \
} \
private: \
static const Register _staticRegister; \
}; \
const Register Register##ClassName::_staticRegister(#ClassName, Register##ClassName::instance);
先经过宏替换,生成一个新类,而且一个静态方法,用于建立对象。最后一行是用于调用新类的静态成员变量,经过此静态成员变量的构造函数,把类注册到哈希里(此处感受Register类设计有点多余,是否能够考虑直接最后一句调用ClassFactory::registerClass(className, fp);来进行类注册,后面再来考虑吧),参数,第一个是类名,第二个是新类的建立对象的函数。到这一步,类反射的功能即将要实现了。
下面咱们来设计最后一个类,就是将要被动态建立的类,先帖码。
class Foo
{
public:
Foo()
{
_id = 1;
_name = "Foo";
}
public:
int _id;
std::string _name;
};
REGISTER(Foo);
Foo类是咱们要动态建立出来的类,REGISTER(Foo)用于把类foo进行宏替换后生成一个新类,用于建立foo的对象的。
到此,全部的准备工做都作好了,接下来就是测试了。
在main中添加代码:
Foo* foo = static_cast<Foo*>(ClassFactory::getInstance("Foo"));
std::cout << foo->_name << std::endl;
当界面上打印输出Foo的时候,就证实是成功了。
到此,C++反射的实现讲解完成,这类实现方法适合在开发各种的编辑器中去使用,包括微软的MFC等等。在开发编辑器的阶段,并无相应的类,可是使用者想经过在编辑器中传入类的名字,而后在开发中,根据编辑器传入的类名,新建一个类去实现的话,这种方法很是适用,更多的用法等待你们去发掘。不足之处欢迎你们指正。
Ps:此方法参考了网友的文章,须要的可参考: