使用过C#或者Java 的童鞋,应该对这些语言提供的反射机制有所了解。所谓反射,在我看来就是在只知道一个类的名字(字符串形式)的情况下,自动创建出具体的类实例,并且能够枚举该类型拥有的属性、方法等信息。使用反射写出来的代码可以做到异常的精致简洁。
公司最近准备开发的产品需要跨平台,使用的是C++语言,然而C++语言并没有内置反射这种机制。于是进行了一番调研。最终一款RTTR库(C++开源库)(github地址:RTTR源码)比较符合现有的业务,而且跨平台,这里记录一下在windows下开发,并以一个例子展示,方便后面遇到同样需求的同学参考;
这里使用的最新的0.9.6版本,环境:windows 10,vs2017,如图:
当然,懒得编译的话0.9.5版本有个编译好的二进制安装包,可以直接下载使用,如图:
准备好之后,进行编译,得到库文件rttr_core.dll,rttr_core.lib,头文件位置:src\rttr,并添加到项目中
自定义一个类Computer
#pragma once
#include "rttr/type"
namespace Device
{
class Computer
{
public:
Computer();
~Computer();
void set_name(const std::string& name);
const std::string& get_name() const;
void set_usedage(int age);
int get_usedage();
void set_sysType(const std::string& sysType);
const std::string& get_sysType() const;
public:
void showProperty();
void showChangedProperty(std::string name, int age, std::string sysType);
private:
std::string m_name;
std::string m_sysType;
int m_age;
RTTR_ENABLE()
};
}
在Computer.cpp实现文件里面加入如下关键代码,所有支持反射功能的属性和方法都是通过这段代码来处理:
RTTR_REGISTRATION
{
rttr::registration::class_<Computer>("Device::Computer").constructor<>()(rttr::policy::ctor::as_std_shared_ptr)
.property("name", &Computer::get_name, &Computer::set_name)
.property("age", &Computer::get_usedage, &Computer::set_usedage)
.property("sysType", &Computer::get_sysType, &Computer::set_sysType)
.method("showProperty", &Computer::showProperty)
.method("showChangedProperty", &Computer::showChangedProperty)
(
rttr::default_arguments(std::string("Dell"),5,std::string("Windows 7"))
,rttr::parameter_names("name","sysType","age")
);
}
之后就是main函数调用了
std::cout << "\nDevice::Computer类:" << std::endl;
rttr::type de = rttr::type::get_by_name("Device::Computer");
rttr::variant var1 = de.create();
rttr::property func_prop = de.get_property("name");
func_prop.set_value(var1, std::string("Lenvo"));
std::cout <<"设置字段:" <<func_prop.get_value(var1).to_string() <<"成功"<< endl;
func_prop = de.get_property("age");
func_prop.set_value(var1, 5);
std::cout << "设置字段:" << func_prop.get_value(var1).to_int() << "成功" << endl;
func_prop = de.get_property("sysType");
func_prop.set_value(var1, std::string("Windows 7"));
std::cout << "设置字段:" << func_prop.get_value(var1).to_string() << "成功" << endl;
rttr::method func_method = de.get_method("showProperty");
func_method.invoke(var1);
rttr::method func_method2 = de.get_method("showChangedProperty");
func_method2.invoke(var1, std::string("ThinkPad"), 3, std::string("Windows 10"));
如此就完成了反射功能,可获取函数名称,函数调用的返回值,当然也可以通过遍历获取类属性名称,属性的类型,函数名称列表,函数对应的参数/参数类型等等,RTTR库完全满足了反射的需求,详细Demo源码已上传,供参考