java自带反射功能,即可以通过类名(字符串)动态生成对应的类实例,c/c++系统并不提供这样的反射功能。
第一步,简洁地说一下反射的实现思路:
- 构建一个空基类,所有需要实现反射的应用类必须 public 继承该类;
- 构建一个专门用于产生应用类实例的工具类 CreateObjectFactory,此类具体功能包括:提供工厂设计模式的唯一单例,并且实现应用类实例化方法的注册,同时支持据名返回 Object 对象指针;
- 构建一个自动注册的工具类 AutoRegister ,此类主要提供函数自动注册;
- 提供反射所需的宏定义头文件;
- 定义应用类,并把宏定义放置到应用类指定的位置。
第二步,本实现的基本结构
第三步,具体实现细节
//Object.h
#pragma once
class Object
{
};
// CreateObjectFactory.h
#pragma once
#include "Object.h"
#include <map>
#include <string>
typedef Object* (*pCreateObject)();
class CreateObjectFactory
{
private:
CreateObjectFactory() {};
~CreateObjectFactory() { delete singleton; };
public:
static CreateObjectFactory& getSingleton();
Object* forName(std::string className);
void registerByName(std::string, pCreateObject);
private:
std::map<std::string, pCreateObject> registerContainer;
static CreateObjectFactory * singleton;
};
//CreateObjectFactory.cpp
#include "CreateObjectFactory.h"
CreateObjectFactory* CreateObjectFactory::singleton = new CreateObjectFactory;
CreateObjectFactory& CreateObjectFactory::getSingleton() {
return *singleton;
}
Object* CreateObjectFactory::forName(std::string className) {
auto it = this->registerContainer.find(className);
if (it != this->registerContainer.end())
{
return it->second();
}
else {
return nullptr;
}
}
void CreateObjectFactory::registerByName(std::string className, pCreateObject functionPointer) {
this->registerContainer.insert(std::make_pair(className, functionPointer));
return;
}
//AutoRegister.h
#pragma once
#include "CreateObjectFactory.h"
class AutoRegister
{
public:
AutoRegister(std::string className, pCreateObject functionPointer);
};
//AutoRegister.cpp
#include "AutoRegister.h"
AutoRegister::AutoRegister(std::string className, pCreateObject functionPointer) {
CreateObjectFactory::getSingleton().registerByName(className, functionPointer);
return;
}
#pragma once
#include "AutoRegister.h"
#define DECLARE_CLASS(className) \
public:\
static Object* createInstance##className();
#define IMPLEMENT_CLASS(className) \
static AutoRegister autoRegister##className(#className, className::createInstance##className);\
Object * className::createInstance##className() {\
return new className();\
}
第四步,测试验证
(1)构建测试类 TestA ,必须满足4个要求,即就是:必须包含反射头文件,必须 public 继承 Object,必须在类体中定义声明宏DECLARE_CLASS,必须在应用类的 .cpp 文件中定义实现宏 IMPLEMENT_CLASS。如下图所示:
(2)具体实现的完整代码如下
//TestA.h
#pragma once
#include "Reflection.h"
class TestA:public Object
{
DECLARE_CLASS(TestA)
public:
void init(int , float);
int getA();
void setA(int);
private:
int a;
float b;
};
//TestA.cpp
#include "TestA.h"
IMPLEMENT_CLASS(TestA)
void TestA::init(int a, float b) {
this->a = a;
this->b = b;
return;
}
int TestA::getA() {
return this->a;
};
void TestA::setA(int a) {
this->a = a;
}
(3)测试用例编写
#include "TestA.h"
#include <iostream>
int main() {
TestA * t = (TestA*)CreateObjectFactory::getSingleton().forName(std::string("TestA"));
TestA* t2 = (TestA*)CreateObjectFactory::getSingleton().forName(std::string("TestA"));
t->init(10, 20);
std::cout<<"TestA t->init(a = 10, b= 20)\ta= "<<t->getA()<<std::endl;
std::cout<<"TestA t2 do nothing \ta= " << t2->getA() << std::endl;
t2->init(30, 40);
std::cout<<"TestA t2->init(a = 30, b= 40)\ta= " << t2->getA() << std::endl;
return 0;
}
(4)测试结果
提示:
- 本设计仅仅是实现通过类名创建类实例,可以引入本实现,完成使用者自己类的简单反射功能。
- 若使用者不厌其烦地手动注册相应的函数,而不采用宏的形式自动注册,则可以优化空间开销。
- 手动注册形式必须先注册完成,然后才能使用反射功能。
- 很显然,Object并非必须,可以用void* 进行技术性改造