C++实现反射---RTTR库的使用
使用过C#或者Java 的童鞋,应该对这些语言提供的反射机制有所了解。所谓反射,在我看来就是在只知道一个类的名字(字符串形式)的情况下,自动创建出具体的类实例,并且能够枚举该类型拥有的属性、方法等信息。使用反射写出来的代码可以做到异常的精致简洁。
由于我们最近开发的产品使用的是C++语言,然而这种语言并没有内置反射这种机制。于是从网上进行了调研,发现了一些不错的提供C++反射支持的库,如CPP-Reflection、Vlpp、ponder等。我们的产品是用VS2013开发的,对C++11的支持不够完善,这些库一般要用VS2015才能编译。最终我选择了一个叫做RTTR的开源库(Github地址:RTTR传送门),有兴趣的童鞋可以自行编译,这里我提供了使用VS2013编译的x64和x86预编译包。
下面用一个简短的示例演示该库的用法:
Person.h
#include <rttr/type>
namespace World
{
class Person
{
public:
Person();
~Person();
void set_name(const std::string& name);
const std::string& get_name() const;
void set_age(int age);
int get_age();
virtual void show();
void growupTo(int age=20);
private:
std::string m_name;
int m_age;
RTTR_ENABLE()
};
}
Person.cpp
#include "Person.h"
#include <rttr/registration>
#include <iostream>
namespace World
{
RTTR_REGISTRATION
{
rttr::registration::class_<Person>("World::Person")
.constructor<>()
(
rttr::policy::ctor::as_std_shared_ptr
)
.property("name", &Person::get_name, &Person::set_name)
.property("age", &Person::get_age, &Person::set_age)
.method("show", &Person::show)
.method("growupTo", &Person::growupTo)
(
rttr::default_arguments(18),
rttr::parameter_names("age")
)
;
}
Person::Person()
:m_age(0)
{
}
Person::~Person()
{
}
void Person::set_name(const std::string& name)
{
m_name = name;
}
const std::string& Person::get_name() const
{
return m_name;
}
void Person::set_age(int age)
{
m_age = age;
}
int Person::get_age()
{
return m_age;
}
void Person::show()
{
std::cout << "我的名字是: " << m_name << ", 我今年" << m_age << "岁" << std::endl;
}
void Person::growupTo(int age/* =20 */)
{
m_age = age;
std::cout << m_name << "长到了: " << m_age << "岁" << std::endl;
}
}
main.cpp
#include <rttr/type>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
rttr::type t = rttr::type::get_by_name("World::Person");
rttr::variant var = t.create();
rttr::property prop = t.get_property("name");
prop.set_value(var, std::string("小明"));
prop = t.get_property("age");
prop.set_value(var, 18);
rttr::method meth = t.get_method("show");
meth.invoke(var);
std::cout << "属性: " << std::endl;
for (auto& prop : t.get_properties())
{
std::cout << "属性名: " << prop.get_name() << ", 属性类性: " << prop.get_type().get_name() << std::endl;
}
std::cout << "方法: " << std::endl;
for (auto& meth : t.get_methods())
{
std::cout << "方法名称: " << meth.get_name() << ", 方法签名: " << meth.get_signature() << std::endl;
for (auto& info : meth.get_parameter_infos())
{
std::cout << "方法参数下标: " << info.get_index() << ", 参数名" << info.get_name() << std::endl;
}
}
getchar();
return 0;
}
可以看到,main.cpp中并没有引用Person.h,但却创建出了Person的实例。
有时可能需要将RTTR中的variant转成具体的某个类,可以看到在Person.cpp中的RTTR_REGISTRATION块中,对Person类的构造函数用了rttr::policy::ctor::as_std_shared_ptr的描述,可选的还有rttr::policy::ctor::as_object和rttr::policy::ctor::as_raw_ptr。这三种情况下,代码的书写方式都不一样,详细的可以参见RTTR的官方教程。下面给出各种情况下的转换写法:
//as_shared_ptr
//std::shared_ptr<World::Person> person = var.get_value<std::shared_ptr<World::Person>>();
//as_raw_ptr
//World::Person* person = var.get_value<World::Person*>();
//as_object
World::Person person = var.get_value<World::Person>();
当然,此时必须要包含Person.h了。
注:若项目编译失败,报了类似error LNK2001: unresolved external symbol "public: static struct rttr::detail::as_object const rttr::policy::ctor::as_object" (?as_object@ctor@policy@rttr@@2U0detail@3@B)的错,需要增加一个预编译宏:RTTR_DLL
----------------------------------------------我是分割线--------------------------------------------------
在实际使用过程中又发现了一些需要注意的问题(一些坑)。我们的项目结构是:首先编译一堆静态链接库(lib),在最终的exe中链接这些文件。有两个问题:
1.这些lib之间也存在引用关系,假设rrtr在lib1中使用,rttr2引用了rtt1,那么在exe中若链接lib1和lib2,若lib2没有定义RTTR_DLL预编译宏的话,会报一个很奇怪的链接错误,因此lib2也需要在项目设置中增加RTTR_DLL。
2.假设在lib1中的class1使用了rttr,然后exe链接lib1,若exe中的所有参与编译的cpp中都没有使用过class1类(包括定义临时变量、全局变量或new一个指针),在根据类名动态创建类时会失败(rttr::type::get_by_name("World::Person"))。我的解决方法是随便找一个参与编译的cpp文件,在文件开头定义一个全局的class1即可。
————————————————
版权声明:本文为CSDN博主「jianingshow」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/jianingshow/article/details/52318413
C++实现反射---RTTR库的使用的更多相关文章
- AspectCore.Extension.Reflection : .NET Core反射扩展库
在从零实现AOP的过程中,难免会需要大量反射相关的操作,虽然在.net 4.5+/.net core中反射的性能有了大幅的优化,但为了追求极致性能,自己实现了部分反射的替代方案,包括构造器调用.方法调 ...
- c++ 反射类型
来自: 实现代码=== // // Created by lizhen on 2017/9/29. // #ifndef BOOST_ALL_CALLBACKFUNCTION_H #define BO ...
- Java编程的逻辑 (84) - 反射
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http: ...
- Android 插件化开发(一):Java 反射技术介绍
写在前面:学习插件化开发推荐书籍<Android 插件化开发指南>,本系列博客所整理知识部分内容出自此书. 在之前的项目架构的博文中,我们提到了项目插件化架构,提到插件化架构不得不提的到J ...
- Qt 如何使用反射?
Qt 如何使用反射? c++ 反射 标准库暂时还没有,那我们来看看如何使用 qt 来进行反射. 反射类的案例 1. 通过注册的类型需找 id 进行实例化该类 myclass.h #include &l ...
- C#反射的实现
一,什么是反射? 1,System.Reflection 命名空间中的类与 System.Type 使你能够获取有关加载的程序集和其中定义的类型的信息,如类.接口和值类型. 可以使用反射在运行时创建. ...
- 别在重复造轮子了,几个值得应用到项目中的 Java 开源库送给你
我是风筝,公众号「古时的风筝」.文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在里面.公众号回复『666』获取高清大图. 风筝我作为一个野路子开发者,直到 ...
- robotframework笔记22
创建测试库 支持的编程语言 机器人框架本身是用写的 Python 和自然的测试 库扩展它可以使用相同的实现 语言. 运行时框架上 Jython ,图书馆也可以 实现使用 Java . 纯Python代 ...
- Android Weekly Notes Issue #254
Android Weekly Issue #254 April 23rd, 2017 Android Weekly Issue #254 本期内容包括: 如何用Kotlin写一个Gradle Plug ...
随机推荐
- namp相关命令大全
常用功能: -探测主机存活- 扫描端口- 探测主机操作系统信息- 检测漏洞 nmap 常用的几个参数 nmap -v ip 显示详细的扫描过程 nmap -p ip 扫描指定端口 nmap -A ...
- Codeforces 587F - Duff is Mad(根号分治+AC 自动机+树状数组)
题面传送门 第一眼看成了 CF547E-- 话说 CF587F 和 CF547E 出题人一样欸--还有另一道 AC 自动机的题 CF696D 也是这位名叫 PrinceOfPersia 的出题人出的- ...
- CF 786 E ALT
CF 786 E ALT 一个居民有两个选择:分配一只宠物,路上都有宠物 一个守卫有两种选择:分配一只宠物,不分配宠物 我们找一个原点,到每个居民都有一条边,表示是否给他宠物 从每个居民向他路上的守卫 ...
- go变量、类的概念以及类的使用方式,嵌套结构体
go变量.类的概念以及类的使用方式,嵌套结构体 Go变量 go使用var声明变量,当声明变量时,这个变量对应的值总是会被初始化.这个值要么用指定的值初始化,要么用零值(即变 量类型的默认值)做初始化. ...
- Hive-insert into table 与 insert overwrite table 区别
区分insert into 和 insert overowrite: 0. 命令格式 INSERT OVERWRITE|INTO TABLE tablename [PARTITION (partcol ...
- 17.Power of Four-Leetcode
#define IMIN numeric_limits<int>::min() #define IMAX numeric_limits<int>::max() class So ...
- PDFium 渲染
PDFium 是 Chromium 的 PDF 渲染引擎,许可协议为 BSD 3-Clause.不同于 Mozilla 基于 HTML5 的 PDF.js,PDFium 是基于 Foxit Softw ...
- 用python写的推箱子搜索程序
1 # -*- coding: gbk -*- 2 from functools import reduce 3 from copy import deepcopy 4 import re 5 def ...
- 【Netty】最透彻的Netty原理架构解析
这可能是目前最透彻的Netty原理架构解析 本文基于 Netty 4.1 展开介绍相关理论模型,使用场景,基本组件.整体架构,知其然且知其所以然,希望给大家在实际开发实践.学习开源项目方面提供参考. ...
- HelloWorldMBean
package mbeanTest; public interface HelloWorldMBean { public String getHello(); public void setHello ...