RTTI 和 C++ 中的可移植性
如果编译器不“支持”RTTI,是否意味着编译器无法处理包含虚函数的类层次结构?或者我是否误解了有关 RTTI 不可移植的文献,而问题出在其他地方?
谢谢大家的意见!
If a compiler doesn't "support" RTTI, does that mean that the compiler can not handle class hierarchies that have virtual functions in them? Or have I been misunderstanding the literature about how RTTI isn't portable, and the issues lie elsewhere?
Thank you all for your comments!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这可能是您正在寻找的更多答案,但这里是:
RTTI 不是“可移植的”意味着如果您使用编译器 A 构建动态库 A,并使用编译器 B 构建与 A 链接的应用程序 B,那么你不能使用RTTI,因为编译器a和b的RTTI实现是不同的。虚函数受到影响只是因为虚函数机制也可能不兼容二进制。
这个问题在90年代中期非常重要,但现在已经过时了。并不是因为编译器现在都已彼此二进制兼容,而是相反:C++ 开发人员现在已经认识到 C++ 库必须作为源代码而不是可链接库提供。对于那些将 C++ 视为 C 的扩展的人来说,这是非常不舒服的,但对于在开源环境中长大的更现代的程序员来说,这根本没有什么特别的。
从 20 世纪 90 年代中期到现在,变化在于人们对什么构成有价值的知识产权和什么不构成有价值的知识产权的态度有所不同。也就是说:实际上已经在美国专利局注册了一项关于“表达模板”的专利。即使是此类专利的持有人也意识到该专利是无法执行的。
C 风格的“头文件和二进制”库长期以来被视为混淆有价值的源代码的一种方法。越来越多的企业开始认识到,这种混淆更多的是弄巧成拙,而不是保护性的:很少有代码能够满足“有价值的知识产权”的地位。大多数人购买库并不是因为它包含特殊的 IP,而是因为购买比自己构建更便宜。事实上:应用知识产权的专业知识远比知识产权本身更有价值。但如果没有人关心这个IP,因为他们不知道它,那么它就不值钱了。
这就是开源的工作原理:IP 被自由分发,作为回报,这些分发者在应用该 IP 时获得咨询费。那些能够为自己解决问题有利可图的人——对他们来说很好。但这不是常态。实际发生的情况是,开发人员了解知识产权,并向雇主推销其购买实现知识产权的产品。是的,整个“开发者社区”都是建立在这个前提之上的。
长话短说:一旦开源运动兴起,二进制(以及随后的 RTTI)兼容性就走上了恐龙之路,同时,C++ 模板库成为常态。 C++ 库很久以前就变成了“仅可分发的源代码”,如 Perl、Python、JavaScript 等。为了使您的 C++ 编译器能够与您使用它编译的所有源代码一起工作,请确保打开 RTTI(包括所有 C++ 标准功能,例如异常) ,并且您链接的所有 C++ 库同样都使用与您用于编译应用程序的相同选项进行编译。
据我所知,有一个(也是唯一一个)编译器默认情况下不启用 RTTI,这是因为还有其他遗留方法可以做同样的事情。要了解这些内容,请阅读 Don Box 的优秀作品“Essential COM”。
This is probably way more of an answer you were looking for, but here goes:
RTTI is not "portable" means that if you use compiler A to build dynamic library A, and use compiler B to build application B that links with A, then you cannot use RTTI, because the RTTI implementations of compiler a and b are different. Virtual function are affected only because the virtual function mechanism may not be binary compatible either.
This issue was very important in the mid 90's, but the issue is now obsolete. Not because compliers have now all become binary compatible with each other, but rather the opposite: C++ developers have now recognized that C++ libraries must be delivered as source code, and not linkable libraries. For those who view C++ as an extension of C, this is very discomforting, but for more modern programmers, who grew up in an open source enviroment, nothing special at all.
What changed between the mid-90's and now is differing attitudes between what constitutes valuable intellectual property and what doesn't. To wit: there is actually a patent registered with USPO on "expression templates." Even the holder of such realizes that the patent is unenforcable.
C style "header and binary" libraries were long seen as a way to obfuscate valuable source code. More and more, business came to recognize that the obfuscation was more self-defeating than protective: there is very little code out there that meets "valuable IP" status. Most people buy libraries not because of the special IP it contains, but because it is cheaper to buy rather than roll their own. In fact: expertise in applying IP is far more valuable than the IP itself. But if no one cares about this IP because theyh don't know about it, then it is not worth very much.
This is how open source works: IP is freely distrbuted, in return those distributors gain consultancy fees in applying that IP. Those who can figure it out for themselves profitably-- well good on them. But it is not the norm. What happpens actually is that a developer understands IP and sells their employer on buying the product that implements it. Yeah, whole "developer communities" are founded on this premise.
To make a long story short: binary (and subsequently RTTI) compatibilty went the way of the dinosaur once the open source movement took off, and concurrently, C++ template libraries became the norm. C++ libraries long ago became "source distributable only" like Perl, Python, JavaScript etc. To make your C++ compiler work with all source that you compile with it, make sure that RTTI is turned on (inideed all C++ standard features, like exceptions), and that all C++ libs you link are likewise commpied with the same options that you used to compile your app.
There is one (and only one) compiler I know of that does not enable RTTI by default, and that is beccause there are other legacy ways to do the same thing. To read about these, pick up a copy of Don Box's excellent work "Essential COM."
虚拟功能不需要 RTTI。
主要用于
dynamic_cast
和typeid
。RTTI is not needed for virtual functions.
It is mainly used for
dynamic_cast
andtypeid
.RTTI 唯一不可移植的部分是从
type_info::name()
返回的字符串格式。即使这样,只要您能为您的编译器找到一个
c++filt
工具,将这样的字符串转换(分解)回兼容的 C++ 类型,这还是有机会的。The only part of RTTI that is unportable is the format of strings returned from
type_info::name()
.Even this has a fighting chance so long as you can find a
c++filt
tool for your compiler that converts (unmangles) such a string back into a compliant C++ type.一般来说,所有现代 C++ 编译器都支持 RTTI...所以忘记它吧。
如今的 RTTI 是可移植的,并且可以在任何现代编译器上正常工作......但是有些特殊
情况可能会发生。
在ELF平台(Linux)下动态加载库(即dlopen)并尝试
对库和可执行文件之间的某个类执行dynamic_cast,如果出现以下情况,可能会失败
您没有传递正确的标志来链接可执行文件(-rdynamic)。
几乎任何其他情况......都可以。
Generally all modern C++ compilers support RTTI... So forget about it.
RTTI today is portable and works fine on any modern compiler... However some special
cases may occur.
Under ELF platforms (Linux) when you load libraries dynamically (i.e. dlopen) and try
to perform dynamic_cast to some class between library and executable it may fail if
you do not pass correct flags for linking executable (-rdynamic).
Almost any other cases... Just works.