1、前言
之前一直想通过配置文件如xml,配置一个类名,通过这个类名创建对象,通过基类指针来指向派生类,管理一系列这样对象,继承,这样的可以不修改管理咧,直接添加或修改配置文件来动态创建管理类,非常方便。由于C++没有反射机制,但是可以实现。
2、实现
(1)为需要反射的类中定义一个创建该类对象的一个回调函数;
(2)设计一个工厂类,类中有一个std::map,用于保存类名和创建实例的回调函数。通过类工厂来动态创建类对象;
(3)RegisterAction类,实际上没什么用,只是在构造函数中把 key,value加入到ClassFactory的map中去,所以需要定义一个对象来执行构造函数,为了简化定义了REGISTER宏
#include <iostream>
#include <string>
#include <map>
using namespace std;
typedef void* (*PCreateObject)(void);
class ClassFactory
{
private:
map<string, PCreateObject> m_classMap;
ClassFactory() {};
public:
void* CreateObjectByName(string className)
{
map<string, PCreateObject>::const_iterator iter;
iter = m_classMap.find(className);
if (iter == m_classMap.end())
return NULL;
else
return iter->second(); //函数指针的调用
}
void registClass(string name, PCreateObject method)
{
m_classMap.insert(pair<string, PCreateObject>(name, method));
}
static ClassFactory& getInstance()
{
{
static ClassFactory cf;
return cf;
}
}
};
class RegisterAction{
public:
RegisterAction(string className,PCreateObject ptrCreateFn){
ClassFactory::getInstance().registClass(className,ptrCreateFn);
}
};
#define REGISTER(className) \
className* objectCreator##className(){ \
return new className; \
} \
RegisterAction g_creatorRegister##className( \
#className,(PCreateObject)objectCreator##className)
class Base
{
public :
virtual void print() = 0;
};
class ClassA :public Base
{
public:
void print()
{
cout << "Print ClassA" << endl;
}
};
REGISTER(ClassA);
class ClassB :public Base
{
public:
void print()
{
cout << "Print ClassB" << endl;
}
};
REGISTER(ClassB);
int main()
{
Base *p = NULL;
p= (Base *)ClassFactory::getInstance().CreateObjectByName("ClassA");
p->print();
p = (Base *)ClassFactory::getInstance().CreateObjectByName("ClassB");
p->print();
return 0;
}
3、xml配置文件设计和读取
<?xml version="1.0" encoding="UTF-8"?>
<config>
<className>ClassA</className>
<className>ClassB</className>
</config>
可以使用开源tinyxml来解析获取类名,进而通过工厂类创建对象。