C++是不支持通过类名称字符串”ClassXX”来生成对象的,也就是说我们可以使用
ClassXX* object =new ClassXX; 来生成对象,
但是不能通过ClassXX* object=new “ClassXX”; 来生成对象。
反射是一种通过程序运行过程中用类名创建对象,并获取类的成员和方法。
Factory.h
#ifndef _FACTORY_H
#define _FACTORY_H
#include<iostream>
using namespace std;
#include<map>
#include<string>
typedef void* (*create_fun)();
#define REGISTER(className) \
className* objectCreator##className(){ \
return new className; \
} \
RegisterAction g_creatorRegister##className( \
#className,(create_fun)objectCreator##className)
class Factory
{
public:
~Factory(){}
void *GetClassByName(string name)
{
std::map<string,create_fun>::iterator ite = my_class.find(name);
if(ite==my_class.end())
return NULL;
else
return ite->second();
}
void RegisterClass(string name,create_fun fun)
{
my_class[name]=fun;
}
static Factory& GetInstance()
{
static Factory f;
return f;
}
private:
Factory(){}
std::map<string,create_fun> my_class;
};
#endif
test.h
#ifndef __TEST_H
#define __TEST_H
#include <iostream>
using namespace std;
class Test{
public:
Test()
{
cout << "call Test Constructor fun" << endl;
}
~Test()
{
cout << "call Test Destructor fun" << endl;
}
void print()
{
cout << "call Test print fun" << endl;
}
};
class RegisterAction{
public:
RegisterAction(string className,create_fun ptrCreateFn){
Factory::GetInstance().RegisterClass(className,ptrCreateFn);
}
};
#endif
main.h
#include"Factory.h"
#include"test.h"
REGISTER(Test);
int main()
{
Test *t = (Test*)Factory::GetInstance().GetClassByName("Test");
if(!t)
{
cout<<"get class error"<<endl;
return 0;
}
else
t->print();
delete t;
system("pause");
return 0;
}
疑问
我们在通过类名称字符串创建类实例的时候,我们还是需要用到类名进行强制类型转换,有了类名称,我们何必还要处心积虑实现反射的功能呢,直接用类名创建实例不就行了么?
答
上面实现的反射只是了基本的反射问题。还有一种应用场景就是我们定义好了基类,给客户继承,但是我们并不知道客户继承基类后的类型名称。我们可以通过配置文件说明客户实现的具体类型名称,这样我们就可以通过类名称字符串来创建客户自定义类的实例了。