## 9.1 基于RTTR实现反射 回顾Unity开发流程:创建 ,然后在编辑器中搜索类名(即脚本名)添加到 。 习以为常的操作,追究下去却没有这么简单!有以下问题需要解决: 搜索类名,添加脚本到GameObject --> 实际上是通过类名,创建类实例。 类的成员变量,可以在编辑器中进行修改 --> 实际上是通过变量名,访问类实例的成员变量。 总结就是两个字: 。 对C#而言,这都不是问题,语言规范就支持反射。 但是C++是不支持反射的,只能手动将类名、成员变量名映射到Class、Property上面。然而实现映射功能,对于C++初学者是个巨大挑战。 幸好有许多开源的绑定实现可以使用,在Github上比较火的就是 。
回顾Unity开发流程:创建Monobehaviour,然后在编辑器中搜索类名(即脚本名)添加到GameObject。
习以为常的操作,追究下去却没有这么简单!有以下问题需要解决:
总结就是两个字:反射。
对C#而言,这都不是问题,语言规范就支持反射。
但是C++是不支持反射的,只能手动将类名、成员变量名映射到Class、Property上面。然而实现映射功能,对于C++初学者是个巨大挑战。
幸好有许多开源的绑定实现可以使用,在Github上比较火的就是RTTR。

官网:https://www.rttr.org/
RTTR提供了运行时类型反射功能,仅需要数行代码就可以将Class、Method、Property与其名字进行映射,下面例子使用RTTR进行映射:
#include <rttr/registration> using namespace rttr; struct MyStruct { MyStruct() {}; void func(double) {}; int data; }; ///使用RTTR 对MyStruct的 Class、Method、Property与其名字进行映射。 RTTR_REGISTRATION { registration::class_<MyStruct>("MyStruct") .constructor<>() .property("data", &MyStruct::data) .method("func", &MyStruct::func); }
创建了RTTR测试项目,介绍了如何使用RTTR。
CLion工程位于 samples\component\test_rttr
这里贴一下代码及注释,方便查看:
//file:samples/component/test_rttr/main.cpp #include <iostream> #include <rttr/registration> using namespace rttr; struct MyStruct { MyStruct() {}; void func(double) {}; int data; }; //使用RTTR 对MyStruct的 Class、Method、Property与其名字进行映射。 RTTR_REGISTRATION { registration::class_<MyStruct>("MyStruct") .constructor<>()(rttr::policy::ctor::as_raw_ptr) .property("data", &MyStruct::data) .method("func", &MyStruct::func); } int main() { std::cout << "Hello, World!" << std::endl; //遍历成员函数(Method)、成员变量(Property) { type t = type::get<MyStruct>(); for (auto& prop : t.get_properties()) std::cout << "name: " << prop.get_name()<<std::endl; for (auto& meth : t.get_methods()) std::cout << "name: " << meth.get_name()<<std::endl; } //通过字符串反射获取Class,并调用构造函数创建实例 { type t = type::get_by_name("MyStruct"); variant var = t.create(); // 创建实例 constructor ctor = t.get_constructor(); // 调用构造函数创建实例 var = ctor.invoke(); std::cout << var.get_type().get_name(); // 输出 std::shared_ptr<MyStruct> } return 0; }
运行结果如下图: