【问题标题】:Implementation of RTTI using typeid使用 typeid 实现 RTTI
【发布时间】:2013-04-22 09:25:37
【问题描述】:

我是学习高级 C++ 主题的新手,所以如果问题听起来太明显,请原谅我。

我一直在阅读有关在C++中我们可以在运行时获取对象类型信息的各种方法,通常称为RTTI。

但是,我对它是如何工作的感到困惑。 我读过一些在解释 RTTI 时经常提到的东西。其中之一是使用 dynamic_cast 将对象动态地转换为其他对象。另一种是在运行时使用 typeid 来确定对象的类型。

我想知道使用 typeid 是否是在 C++ 中实现 RTTI 的正确方法,如果是,那么 typeid 运算符实际上如何能够在运行时确定对象的类型(它是否分析了内存中的对象 blob?)

如果使用 typeid 不是正确的方法,那么请提出一些其他的实现方法。

【问题讨论】:

  • 看起来你把它弄反了。 typeid 可以工作,因为 RTTI 是在编译器中实现的,所以询问是否使用 typeid“实现 RTTI”看起来很困惑。 “实施 RTTI”到底是什么意思?
  • 你想解决什么问题让你认为你需要 RTTI 和/或 typeid?
  • C++ RTTI 系统是reflection 的一个非常差且没有功能的变体。我个人的看法是,无论使用哪种语言,你都应该尽可能地避免设计中的任何反思需求。
  • 我只是想很好地掌握 RTTI 的概念。我在很多地方都读到过 typeid 运算符可用于确定所讨论对象的运行时类型(当然,确定对象类型的问题会出现在图片中继承时)。但是,我不太了解 dynamic_cast 与 RTTI 有什么关系。
  • dynamic_casttypeid 都依赖于名为 RTTI 的语言功能。如果您的源代码使用其中任何一个,则需要 RTTI 才能编译程序。但是,RTTI 需要很小的运行时开销,因此某些编译器允许您将其关闭。这就是为什么我们希望“typeiddynamic_cast”有一个通用名称,而不是孤立地讨论它们。

标签: c++ oop rtti


【解决方案1】:

RTTI 仅适用于具有虚函数的类的实例。在这种情况下,编译器会在类中添加一个特殊成员,调用虚拟表指针。每个具有虚函数的类都有自己的虚表。通过检查所指向的虚拟表,可以确定对象的具体类型。

【讨论】:

    【解决方案2】:

    重要提示:
    理想情况下,如果您需要识别对象的类型,您需要重新审视您的设计,因为您很可能错过了那里的某些东西并且您违反了 OOP 的 SOLID 规则.

    C++ 标准提供dynamic_casttypeid 作为确定对象的类型 的两种方法。两者都有其优点和局限性。他们如何识别 type 是一个依赖于实现的细节,但通常他们通过在对象的 vtable 中维护指向类型信息结构的指针来做到这一点。如果您完全不知道 vtable 是什么,Marshal Clines C++ Faq 提供了很好的解释 here

    您可以在
    Technical Report on C++ Performance

    中找到大多数编译器使用的实现细节

    相关摘录:

    5.3.7 类型信息

    给定一个多态类的对象(一个至少有一个虚函数的类),一个 type_info 对象可以通过使用 typeid 操作符来获得。在 原理,这是一个简单的操作,涉及到找到虚函数表, 通过找到该对象所属的最派生类对象,然后从该对象的虚函数表中提取指向 type_info 对象的指针(或 等价的)。


    5.3.8 动态投射

    给定一个指向多态类对象的指针,转换为指向另一个基类的指针 同一派生类对象的子对象可以使用 dynamic_cast 来完成。在 原理,这个操作涉及到找到虚函数表,通过那个找到 对象所属的最派生类对象,然后使用类型信息 与该对象关联以确定是否允许转换(强制转换),最后 对 this 指针进行任何必要的调整。原则上,这种检查 涉及描述最派生的基类的数据结构的遍历 班级。因此,dynamic_cast 的运行时成本可能取决于相对位置 在所涉及的两个类的类层次结构中。

    【讨论】:

    • 在此处提供的摘录中,提到 RTTI 使用简单的 vtable 来获取类型信息。无论如何,具有虚函数的类已经有一个 vtable。那么 RTTI 是如何造成额外的性能开销的呢?
    猜你喜欢
    • 1970-01-01
    • 2012-02-02
    • 2012-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-28
    • 2015-04-21
    相关资源
    最近更新 更多