概念
简而言之,反射就是对象类型在编译期是未知的,在运行期动态的创建的,通过名字获取该类的一个实例。
class Person {
public:
virtual void show() = 0;
}
class Allen : public Person {
virtual void show() {
std::cout << "Hello, I'm Allen!" << std::endl;
}
}
Person *p = new Allen();
p->show();
首先获取对象
std::string className = /从配置文件中读取/
*p = getNewInstance
C++实现发射方案 —— 对象工厂
对象工厂是一种可以间接实例化对象的类。
class ObjectFactory{
virtual ReflectObject* newInstance() = 0;
}
class ObjectFactory_Allen : public ObjectFactory{
ReflectObject* newInstance(){
// 这里注意一点就是,所有能够被反射的类都继承自 ReflectObject 这个类。
return new Allen();
};
}
通过对象工厂构造具体的对象
ObjectFactory *of = new ObjectFactory_Allen();
// 有了对象工厂的实例后,就可以产生 Allen 对象的实例了
ReflectObject *allen= of->newInstance();
// 接下来可以使用类型转换,把 allen 对象转换成 Person
Person *p = dynamic_cast<Person*>(allen);
反射器
反射器实际上也是一个类,它管理了类名到对象工厂实例之间的映射关系。反射器对象在程序中是一个全局唯一的对象。这种映射关系看起来就像一张表:
(“Allen”, Allen 的对象工厂的实例对象);
(“Luffy”, Luffy 的对象工厂的实例对象);
(“Zoro”, Zoro 的对象工厂的实例对象);
只要未来你想要编写一个新的类,比如 Bob 类,那么你就必须要同时编写 Allen 的工厂类 ObjectFactory_Bob,同时,你还得实例化一个这个工厂类的对象 objectFactory_Bob = new ObjectFactory_Bob(),并将 (“Bob”, objectFactory_Bob) 这种映射关系保存到反射器中。
class Reflector
{
public:
Reflector();
~Reflector();
// 如果你要反射你的类,就必须将你的类名,以及工厂实例对象注册到反射器中。
void registerFactory(const std::string& className, ObjectFactory *of);
// 反射器可以根据对象工厂实例来生产实例对象。请参考 2.2 节
ReflectObject* getNewInstance(const std::string& className);
private:
std::map<std::string, ObjectFactory*> objectFactories;
};
开发流程:
- 编写一个类继承ReflectObject类
- 编写一个对应的工厂类,并实例化一个工厂类对象
- 调用反射器的registerFactory接口,讲类名和工厂类对象注册掉反射器
demo:
第一步: 定义一个allen类 ```cpp class ReflectObject{ }
class allen : public ReflectObject{ }
第二步: 定义allen类对应的工厂类<br />
```cpp
class ObjectFactory{
virtual ReflectObject* newInstance() = 0;
}
class ObjectFactory_Allen : public ObjectFactory{
ReflectObject* newInstance(){
return new Allen();
};
}
第三步: 创建工厂类对象,注册到反射器中
// 函数 reflector 可以用来获取反射器对象。
reflector().registerFactory("Allen", new ObjectFactory_Allen());
第四步: 使用时获取allen类对象
Person *allen = getNewInstance<Person>("Allen");
宏定义实现反射
/***********需要被反射的类,需要在其对应的 cpp 文件中进行反射声明***********/
#define REFLECT(name)\
class ObjectFactory_##name : public ObjectFactory{\
public:\
ReflectObject* newInstance() {\
return new name(); \
}\
}; \
class Register_##name{\
public:\
Register_##name(){\
reflector().registerFactory(#name, new ObjectFactory_##name()); \
}\
};\
Register_##name register_##name;
这样的话, demo的第二三步可以简化为:
REFLECT(Allen);
完整示例:
反射器类具体代码
// Reflect.h
#pragma once
#include <string>
#include <map>
#include <iostream>
/********************所有需要实现反射的类需要继承它************************/
class ReflectObject {
public:
virtual ~ReflectObject(){}
};
/************************************************************************/
/******************对象工厂抽象类,用来生成对象实例************************/
class ObjectFactory {
public:
ObjectFactory(){ std::cout << "ObjectFactory()" << std::endl; }
virtual ~ObjectFactory(){ std::cout << "~ObjectFactory()" << std::endl; }
virtual ReflectObject* newInstance() = 0;
};
/************************************************************************/
/***********反射器,用来管理(对象名,对象工厂)的映射关系******************/
class Reflector
{
public:
Reflector();
~Reflector();
void registerFactory(const std::string& className, ObjectFactory *of);
ReflectObject* getNewInstance(const std::string& className);
private:
std::map<std::string, ObjectFactory*> objectFactories;
};
/************************************************************************/
/**********************获取反射器实例,全局唯一****************************/
Reflector& reflector();
/************************************************************************/
/***********需要被反射的类,需要在其对应的 cpp 文件中进行反射声明***********/
#define REFLECT(name)\
class ObjectFactory_##name : public ObjectFactory{\
public:\
ObjectFactory_##name(){ std::cout << "ObjectFactory_" << #name << "()" << std::endl; }\
virtual ~ObjectFactory_##name(){ std::cout << "~ObjectFactory_" << #name << "()" << std::endl; }\
ReflectObject* newInstance() {\
return new name(); \
}\
}; \
class Register_##name{\
public:\
Register_##name(){\
reflector().registerFactory(#name, new ObjectFactory_##name()); \
}\
};\
Register_##name register_##name;
/************************************************************************/
/***********************根据类名获取对象实例******************************/
template<typename T>
T* getNewInstance(const std::string& className) {
return dynamic_cast<T*>(reflector().getNewInstance(className));
}
// Reflector.cpp
#include "Reflector.h"
Reflector::Reflector()
{
}
Reflector::~Reflector()
{
std::map<std::string, ObjectFactory*>::iterator it = objectFactories.begin();
for (; it != objectFactories.end();++it)
{
delete it->second;
}
objectFactories.clear();
}
void Reflector::registerFactory(const std::string& className, ObjectFactory *of)
{
std::map<std::string, ObjectFactory*>::iterator it = objectFactories.find(className);
if (it != objectFactories.end()) {
std::cout << "该类已经存在……" << std::endl;
}
else {
objectFactories[className] = of;
}
}
ReflectObject* Reflector::getNewInstance(const std::string& className)
{
std::map<std::string, ObjectFactory*>::iterator it = objectFactories.find(className);
if (it != objectFactories.end()) {
ObjectFactory *of = it->second;
return of->newInstance();
}
return NULL;
}
// 用来获取反射器对象,注意这是全局唯一的。
Reflector& reflector() {
static Reflector reflector;
return reflector;
}
抽象对象类的实现
// Person.h
#include "Reflector.h"
// 让 Person 继承反射基类
class Person : public ReflectObject
{
public:
Person();
virtual ~Person();
virtual void show();
};
// Person.cpp
Person::Person()
{
std::cout << "Person()" << std::endl;
}
Person::~Person()
{
std::cout << "~Person()" << std::endl;
}
void Person::show()
{
std::cout << "Hello, I'm person" << std::endl;
}
具体对象类的实现
#include "Person.h"
class Allen : public Person
{
public:
Allen()
virtual ~Allen();
virtual void show();
};
class Luffy : public Person
{
public:
Luffy();
virtual ~Luffy();
virtual void show();
};
REFLECT(Allen);// 注册反射类,只能写在 cpp 文件中。
Allen::Allen()
{
std::cout << "Allen()" << std::endl;
}
Allen::~Allen()
{
std::cout << "~Allen()" << std::endl;
}
void Allen::show()
{
std::cout << "Hello, I'm Allen" << std::endl;
}
REFLECT(Luffy); // 注册反射类,只能写在 cpp 文件中。
Luffy::Luffy()
{
std::cout << "Luffy()" << std::endl;
}
Luffy::~Luffy()
{
std::cout << "~Luffy()" << std::endl;
}
void Luffy::show()
{
std::cout << "Hello, I'm Luffy" << std::endl;
}
这是一个完整的反射的实现和测试实例,文章参考自
https://blog.csdn.net/q1007729991/article/details/56012253