由于课程项目要求,要能够在程序运行时获取场景中对象的属性与方法,在网上了解到了反射机制,但C++都未能支持反射机制,在C++中要实现类似Java等语言的反射机制需要另外写代码保存类型相关信息,然后在运行时使用。所以了解到了RTTR, rttr提供对象的成员数据类型,通过rttr获取每一个对象的的属性,读取起数据类型和值,然后利用这些信息自动保存数据,也能利用这些信息自动解析数据。
在官网下载完成后,cmake即可。
rttr的使用
1、首先写一些类或结构体
// 颜色类
enum class color
{
red,
green,
blue
};
// (x,y)点
struct point2d
{
point2d() {}
point2d(int x_, int y_) : x(x_), y(y_) {}
int x = 0;
int y = 0;
};
// 形状类
struct shape
{
shape(std::string n) : name(n) {}
void set_visible(bool v) { visible = v; }
bool get_visible() const { return visible; }
color color_ = color::blue;
std::string name = "";
point2d position;
std::map<color, point2d> dictionary;
RTTR_ENABLE()
private:
bool visible = false;
};
// 圆
struct circle : shape
{
circle(std::string n) : shape(n) {}
double radius = 5.2;
std::vector<point2d> points;
int no_serialize = 100;
RTTR_ENABLE(shape)
};
2、手动注册属性方法和构造函数
RTTR_REGISTRATION
{
rttr::registration::class_<shape>("shape")
.property("visible", &shape::get_visible, &shape::set_visible)
.property("color", &shape::color_)
.property("name", &shape::name)
.property("position", &shape::position)
.property("dictionary", &shape::dictionary)
;
rttr::registration::class_<circle>("circle")
.property("radius", &circle::radius)
.property("points", &circle::points)
.property("no_serialize", &circle::no_serialize)
(
metadata("NO_SERIALIZE", true)
)
;
rttr::registration::class_<point2d>("point2d")
.constructor()(rttr::policy::ctor::as_object)
.property("x", &point2d::x)
.property("y", &point2d::y)
;
rttr::registration::enumeration<color>("color")
(
value("red", color::red),
value("blue", color::blue),
value("green", color::green)
);
}
3、使用1——将对象转为json数据
①先创建一个circle的对象
circle c_1("Circle #1");
shape& my_shape = c_1;
c_1.set_visible(true);
c_1.points = std::vector<point2d>(2, point2d(1, 1));
c_1.points[1].x = 23;
c_1.points[1].y = 42;
c_1.position.x = 12;
c_1.position.y = 66;
c_1.radius = 5.123;
c_1.color_ = color::red;
c_1.dictionary = { { {color::green, {1, 2} }, {color::blue, {3, 4} }, {color::red, {5, 6} } } };
c_1.no_serialize = 12345;
②转为json数据,只需要一句话
json_string = io::to_json(my_shape);
结果:
4、使用2——利用已有的json数据,新生成一个对象
接下来创建一个新的圆circle2,name="Circle #2"
circle c_2("Circle #2");
将circle1的json数据,反序列化后的内容用于给circle2的属性赋值
io::from_json(json_string, c_2);
输出circle2的json数据后,也能验证和circle的数据内容是一致的。