一、引言
在很多高级语言(如 C#/Java)中,“反射”是一种内省机制,允许程序在运行时查看和操作对象的结构与行为(如类名、字段、方法等)。而 C++ 作为静态语言,默认并不支持强反射机制。
尽管 C++ 提供 RTTI(如 typeid
和 dynamic_cast
),但其功能非常有限,并且很多高性能或嵌入式环境都禁用了 RTTI。
本文将从零开始,实现一个纯 C++ 的运行时反射系统,不依赖 RTTI,可实现字段注册、类型名称、对象属性遍历、动态构造等能力。
二、反射系统的应用场景
场景
用途
编辑器
属性面板展示与绑定
脚本接口
反射 C++ 对象给 Lua/Python
序列化
将对象自动转为 JSON/XML/Binary
插件系统
不同模块之间的统一字段解析与操作
网络通信
自动化消息结构注册与生成
三、目标功能概览
我们的运行时反射系统应具备以下能力:
-
注册类型信息(类名、字段)
-
动态构造对象(new 及析构)
-
遍历字段,获取/设置值
-
查询字段类型、名称、偏移量
-
跨模块兼容性(不依赖 RTTI)
四、核心设计思路
设计三个核心类:
-
Type
:表示一个类的信息 -
Field
:表示类的一个字段(属性) -
TypeRegistry
:集中管理所有注册的类型
我们通过宏 + 模板封装类信息,在运行时自动注册。
五、字段描述结构 Field
cpp复制编辑struct Field {
std::string name;
std::string type;
size_t offset;
template<typename T>
T& get(void* instance) const {
return *reinterpret_cast<T*>((char*)instance + offset);
}
};
六、类型信息结构 Type
cpp复制编辑struct Type {
std::string name;
size_t size;
std::function<void*(void)> creator;
std::function<void(void*)> deleter;
std::vector<Field> fields;
void* create() const { return creator(); }
void destroy(void* obj) const { deleter(obj); }
};
七、注册表 TypeRegistry
cpp复制编辑class TypeRegistry {
public:
static TypeRegistry& instance() {
static TypeRegistry inst;
return inst;
}
void registerType(const std::string& name, const Type& t) {
types_[name] = t;
}
const Type* get(const std::string& name) const {
auto it = types_.find(name);
return it != types_.end() ? &it->second : nullptr;
}
private:
std::unordered_map<std::string, Type> types_;
};
八、反射注册宏与辅助函数
cpp复制编辑#define BEGIN_REFLECT(T) \
namespace { \
struct T##_Reflector { \
T##_Reflector() { \
Type t; \
t.name = #T; \
t.size = sizeof(T); \
t.creator = []() -> void* { return new T(); }; \
t.deleter = [](void* obj) { delete (T*)obj; };
#define REFLECT_FIELD(field, type) \
t.fields.push_back(Field{#field, #type, offsetof(T, field)});
#define END_REFLECT(T) \
TypeRegistry::instance().registerType(#T, t); \
} \
}; static T##_Reflector global_reflector_##T; }
九、定义一个可反射的类
cpp复制编辑struct Person {
std::string name;
int age;
float height;
};
BEGIN_REFLECT(Person)
REFLECT_FIELD(name, std::string)
REFLECT_FIELD(age, int)
REFLECT_FIELD(height, float)
END_REFLECT(Person)