我希望能够自省一个c++类的名称,内容(即成员及其类型)等。这里我说的是原生c++,而不是托管c++,托管c++有反射。我意识到c++使用RTTI提供了一些有限的信息。哪些附加库(或其他技术)可以提供这些信息?
当前回答
我想你可能会对Dominic Filion写的“在c++中使用反射模板”这篇文章感兴趣。它在Game Programming Gems 5的1.4部分。不幸的是,我没有带我的副本,但你可以找找看,因为我认为它解释了你想要的东西。
其他回答
尽管在c++中不支持即时可用的反射,但实现它并不太难。 我遇到了这篇很棒的文章: http://replicaisland.blogspot.co.il/2010/11/building-reflective-object-system-in-c.html
本文详细介绍了如何实现一个非常简单的反射系统。当然,这不是最有益的解决办法,还有一些粗糙的地方有待解决,但对我的需要来说,这已经足够了。
底线——如果做得正确,反射是可以得到回报的,而且在c++中是完全可行的。
你想用反射做什么? 可以使用Boost类型特征和typeof库作为编译时反射的有限形式。也就是说,您可以检查和修改传递给模板的类型的基本属性。
RareCpp库实现了相当简单和直观的反射——所有字段/类型信息都被设计成可以在数组中使用,或者感觉像是数组访问。它是为c++ 17编写的,可与Visual Studios、g++和Clang一起使用。这个库只有头文件,这意味着你只需要将“Reflect.h”复制到你的项目中就可以使用它。
被反射的结构体或类需要REFLECT宏,在该宏中您可以提供所反射的类的名称和字段的名称。
class FuelTank {
public:
float capacity;
float currentLevel;
float tickMarks[2];
REFLECT(FuelTank, capacity, currentLevel, tickMarks)
};
这就是全部内容,不需要额外的代码来设置反射。可选地,您可以提供类和字段注释,以便能够遍历超类或向字段添加额外的编译时信息(例如Json::Ignore)。
遍历字段可以简单到…
for ( size_t i=0; i<FuelTank::Class::TotalFields; i++ )
std::cout << FuelTank::Class::Fields[i].name << std::endl;
您可以通过对象实例循环访问字段值(您可以读取或修改)和字段类型信息……
FuelTank::Class::ForEachField(fuelTank, [&](auto & field, auto & value) {
using Type = typename std::remove_reference<decltype(value)>::type;
std::cout << TypeToStr<Type>() << " " << field.name << ": " << value << std::endl;
});
JSON库构建在RandomAccessReflection之上,它可以自动识别适当的JSON输出表示来读写,并且可以递归遍历任何反射字段,以及数组和STL容器。
struct MyOtherObject { int myOtherInt; REFLECT(MyOtherObject, myOtherInt) };
struct MyObject
{
int myInt;
std::string myString;
MyOtherObject myOtherObject;
std::vector<int> myIntCollection;
REFLECT(MyObject, myInt, myString, myOtherObject, myIntCollection)
};
int main()
{
MyObject myObject = {};
std::cout << "Enter MyObject:" << std::endl;
std::cin >> Json::in(myObject);
std::cout << std::endl << std::endl << "You entered:" << std::endl;
std::cout << Json::pretty(myObject);
}
上面的代码可以这样运行……
Enter MyObject:
{
"myInt": 1337, "myString": "stringy", "myIntCollection": [2,4,6],
"myOtherObject": {
"myOtherInt": 9001
}
}
You entered:
{
"myInt": 1337,
"myString": "stringy",
"myOtherObject": {
"myOtherInt": 9001
},
"myIntCollection": [ 2, 4, 6 ]
}
参见……
反映文档 反映实现 更多用法示例
我想你可能会对Dominic Filion写的“在c++中使用反射模板”这篇文章感兴趣。它在Game Programming Gems 5的1.4部分。不幸的是,我没有带我的副本,但你可以找找看,因为我认为它解释了你想要的东西。
我建议使用Qt。
有一个开源许可证和一个商业许可证。
推荐文章
- 如何构建和使用谷歌TensorFlow c++ api
- 断言是邪恶的吗?
- 下面这些短语在c++中是什么意思:0 -,default-和value-initialization?
- 在STL地图中,使用map::insert比[]更好吗?
- C++ Linux的想法?
- 如何为Fedora安装g++ ?
- Std::cin输入空格?
- c++标准是否要求iostreams的性能很差,或者我只是在处理一个糟糕的实现?
- gcc在哪里查找C和c++头文件?
- 为什么我们需要require require ?
- 解析c++中的命令行参数?
- 我如何在c++中创建一个随机的字母数字字符串?
- c++中的atan和atan2有什么区别?
- 现代c++能让你免费获得性能吗?
- 一门语言是如何自我扩展的?