我希望能够自省一个c++类的名称,内容(即成员及其类型)等。这里我说的是原生c++,而不是托管c++,托管c++有反射。我意识到c++使用RTTI提供了一些有限的信息。哪些附加库(或其他技术)可以提供这些信息?
当前回答
编辑:不再维护CAMP;有两个fork可供选择:
其中一个也被称为CAMP,并且基于相同的API。 思考是部分重写,应该优先考虑,因为它不需要Boost;它使用c++ 11。
CAMP是MIT授权的库(以前是LGPL),它向c++语言添加了反射。它在编译中不需要特定的预处理步骤,但是必须手动进行绑定。
目前的Tegesoft库使用Boost,但也有一个使用c++ 11的分支不再需要Boost。
其他回答
你想用反射做什么? 可以使用Boost类型特征和typeof库作为编译时反射的有限形式。也就是说,您可以检查和修改传递给模板的类型的基本属性。
I did something like what you're after once, and while it's possible to get some level of reflection and access to higher-level features, the maintenance headache might not be worth it. My system was used to keep the UI classes completely separated from the business logic through delegation akin to Objective-C's concept of message passing and forwarding. The way to do it is to create some base class that is capable of mapping symbols (I used a string pool but you could do it with enums if you prefer speed and compile-time error handling over total flexibility) to function pointers (actually not pure function pointers, but something similar to what Boost has with Boost.Function--which I didn't have access to at the time). You can do the same thing for your member variables as long as you have some common base class capable of representing any value. The entire system was an unabashed ripoff of Key-Value Coding and Delegation, with a few side effects that were perhaps worth the sheer amount of time necessary to get every class that used the system to match all of its methods and members up with legal calls: 1) Any class could call any method on any other class without having to include headers or write fake base classes so the interface could be predefined for the compiler; and 2) The getters and setters of the member variables were easy to make thread-safe because changing or accessing their values was always done through 2 methods in the base class of all objects.
It also led to the possibility of doing some really weird things that otherwise aren't easy in C++. For example I could create an Array object that contained arbitrary items of any type, including itself, and create new arrays dynamically by passing a message to all array items and collecting the return values (similar to map in Lisp). Another was the implementation of key-value observing, whereby I was able to set up the UI to respond immediately to changes in the members of backend classes instead of constantly polling the data or unnecessarily redrawing the display.
也许您更感兴趣的是,您还可以转储为类定义的所有方法和成员,而且是字符串形式。
该系统的缺点可能会让您望而却步:添加所有消息和键值非常繁琐;它比没有反射要慢;你会讨厌看到boost::static_pointer_cast和boost::dynamic_pointer_cast遍布你的代码库;强类型系统的局限性仍然存在,您实际上只是将它们隐藏了一些,所以它不那么明显。字符串中的错别字也不是一个有趣或容易发现的惊喜。
As to how to implement something like this: just use shared and weak pointers to some common base (mine was very imaginatively called "Object") and derive for all the types you want to use. I'd recommend installing Boost.Function instead of doing it the way I did, which was with some custom crap and a ton of ugly macros to wrap the function pointer calls. Since everything is mapped, inspecting objects is just a matter of iterating through all of the keys. Since my classes were essentially as close to a direct ripoff of Cocoa as possible using only C++, if you want something like that then I'd suggest using the Cocoa documentation as a blueprint.
我也想要一匹小马,但小马不是免费的。: - p
http://en.wikibooks.org/wiki/C%2B%2B_Programming/RTTI是你将得到的。像您所考虑的反射——运行时可用的完整描述性元数据——在默认情况下c++中不存在。
我想你可能会对Dominic Filion写的“在c++中使用反射模板”这篇文章感兴趣。它在Game Programming Gems 5的1.4部分。不幸的是,我没有带我的副本,但你可以找找看,因为我认为它解释了你想要的东西。
反射本质上是关于编译器决定在运行时代码可以查询的代码中留下哪些足迹。c++以不为不用的东西付费而闻名;因为大多数人不使用/不想要反射,c++编译器通过不记录任何东西来避免成本。
因此,c++不提供反射,并且像其他答案所指出的那样,作为一般规则,自己“模拟”它并不容易。
在“其他技术”下,如果没有带有反射的语言,可以使用一个可以在编译时提取所需信息的工具。
我们的DMS软件再造工具包是通过显式语言定义参数化的通用编译器技术。它有语言定义C, c++, Java, COBOL, PHP,…
对于C、c++、Java和COBOL版本,它提供了对解析树和符号表信息的完整访问。符号表信息包括您可能希望从“反射”中获得的数据类型。如果您的目标是枚举一组字段或方法,并对它们做一些事情,DMS可以用于根据符号表中的内容以任意方式转换代码。
推荐文章
- decltype(auto)的一些用途是什么?
- Shared_ptr转换为数组:应该使用它吗?
- Printf与std::字符串?
- 禁用复制构造函数
- 只接受特定类型的c++模板
- c#和Java中的泛型有什么不同?和模板在c++ ?
- 即使模板文件存在,Flask也会引发TemplateNotFound错误
- c++ 11中的递归lambda函数
- 在c++中指针使用NULL或0(零)吗?
- 在c++中,如何将int值附加到字符串中?
- 就性能而言,使用std::memcpy()还是std::copy()更好?
- 为什么布尔值是1字节而不是1位?
- 四舍五入到一个数字的最接近倍数
- jQuery模板引擎
- 模板默认参数