我是靠谱客的博主 追寻歌曲,最近开发中收集的这篇文章主要介绍【C++实现反射---RTTR库的使用】Person.hPerson.cppmain.cpp注意,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

文章目录

  • Person.h
  • Person.cpp
  • main.cpp
  • 注意


在这里插入图片描述

使用过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即可。

最后

以上就是追寻歌曲为你收集整理的【C++实现反射---RTTR库的使用】Person.hPerson.cppmain.cpp注意的全部内容,希望文章能够帮你解决【C++实现反射---RTTR库的使用】Person.hPerson.cppmain.cpp注意所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(50)

评论列表共有 0 条评论

立即
投稿
返回
顶部