RTTR(Run Time Type Reflection)是一个轻量级、跨平台的C++运行时反射库。它解决了C++语言本身缺乏反射机制的问题,让开发者能够在运行时获取和操作类型信息。与需要编译器扩展的方案不同,RTTR完全基于标准C++实现,支持Windows、Linux和macOS等主流平台。
在实际项目中,RTTR特别适合以下场景:
注意:RTTR虽然功能强大,但反射操作相比直接调用会有一定性能开销,建议在非性能关键路径使用。
这是最灵活的集成方式,适合需要自定义修改或特殊集成的项目:
include目录添加到项目头文件搜索路径src/rttr/rttr_core.cpp文件关键点:
对于使用vcpkg的项目,可以简单执行:
bash复制vcpkg install rttr
安装完成后,在CMake项目中可以这样使用:
cmake复制find_package(RTTR REQUIRED)
target_link_libraries(your_target PRIVATE RTTR::Core)
完整CMake配置示例:
cmake复制cmake_minimum_required(VERSION 3.10)
project(MyRttrProject)
set(CMAKE_CXX_STANDARD 17)
# 查找RTTR包
find_package(RTTR REQUIRED)
add_executable(my_app main.cpp)
target_link_libraries(my_app PRIVATE RTTR::Core)
RTTR的核心是类型注册系统。每个需要反射的类都需要通过RTTR_REGISTRATION宏进行注册:
cpp复制class MyClass {
public:
int value;
void print() { /*...*/ }
};
RTTR_REGISTRATION {
rttr::registration::class_<MyClass>("MyClass")
.property("value", &MyClass::value)
.method("print", &MyClass::print);
}
注册时需要注意:
注册后就可以在运行时操作对象:
cpp复制rttr::type t = rttr::type::get<MyClass>();
rttr::variant obj = t.create(); // 创建实例
// 设置属性
obj.set_property("value", 42);
// 调用方法
obj.invoke("print");
RTTR可以正确处理类继承关系:
cpp复制class Base { /*...*/ };
class Derived : public Base { /*...*/ };
RTTR_REGISTRATION {
registration::class_<Base>("Base");
registration::class_<Derived, Base>("Derived");
}
使用时可以通过get_derived_classes()获取所有子类信息。
枚举类型的反射支持:
cpp复制enum class Color { Red, Green, Blue };
RTTR_REGISTRATION {
registration::enumeration<Color>("Color")
(value("Red", Color::Red),
value("Green", Color::Green),
value("Blue", Color::Blue));
}
虽然RTTR很高效,但在性能敏感场景可以考虑:
实测数据显示,经过优化的反射调用开销可以控制在直接调用的2-3倍内。
在游戏开发中,我们使用RTTR实现了场景对象的自动序列化:
cpp复制void SerializeObject(rttr::instance obj, json& j) {
auto type = obj.get_type();
for (auto& prop : type.get_properties()) {
j[prop.get_name()] = SerializeValue(prop.get_value(obj));
}
}
这个方案使我们新增游戏对象类型时,序列化代码无需修改。
编辑器中使用RTTR动态生成属性UI:
cpp复制void CreatePropertyUI(rttr::property prop, rttr::instance obj) {
auto type = prop.get_type();
if (type == rttr::type::get<int>()) {
CreateIntSlider(prop, obj);
}
else if (type == rttr::type::get<float>()) {
CreateFloatField(prop, obj);
}
// ...
}
当反射类型分布在多个动态库中时,需要注意:
RTTR对模板类的支持有限,建议:
经过多个项目实践,我们总结出以下经验:
对于大型项目,建议建立代码生成机制,自动维护反射注册代码,减少人工维护成本。