如果没有RTTI,C ++中的dynamic_cast不起作用;为什么?

时间:2018-02-16 00:11:56

标签: c++ casting rtti downcast

虚拟方法在没有RTTI的情况下工作,不应该意味着在运行时有足够的数据来确定它是哪个类吗?

(我想知道我如何向下转换,然后检查它是否是指向正确类型的指针。但我无法修改所涉及的类或打开RTTI。)

2 个答案:

答案 0 :(得分:2)

虚拟函数调度不需要类型信息,动态类型的标识。

虚函数调度通常通过每个对象中的vtable指针实现,其中该指针指向特定于类型的函数实现指针表(" vtable")。

dynamic_casttypeid需要输入类型信息。

如果typeid返回类型信息,则该信息必须存在于可执行文件的某个位置。当您关闭信息的存储时,它不会被检索。但是dynamic_cast呢?

在最简单的情况下,dynamic_cast是从某个基本类型引用向下转换为派生类型引用,D&。派生类型不必是对象的派生类型最多。因此,对于现在用于动态调度的通用vtable方案,对象的vtable指针不需要指向D类型的vtable,因此不能提供简单的成功检查

仍然对于仅限于单一继承的语言,可以通过使用vtable本身作为类型标识符来解决纯粹的低位情况,方法是通过vtable中的父指针搜索(单个)继承链。

在图片中有多重继承,事情变得复杂。例如,如果类Derived继承自Base1Base2,两者都是多态的,那么Derived类' vtable不能简单地扩展Base1的vtable 只是扩展Base2的vtable。因此,如果Derived vtable延伸Base1,那么当人们将Derived*重新解释为Base2*时,指向的对象{{1} vtable指针将不再用作指向静态已知类的指针。虚表。

因此,一个结果是,在存在多重继承的情况下,转换为基类型引用并不总是对指针类型的简单重新解释 - 可能必须调整指针值。

如何做到这一点是非常明显的,Bjarne Stroustrup必须向自己证明,在向该语言添加多重继承之前,可以实现多重继承的vtable方案。

我不知道当前的编译器如何处理它,特别是对于Derived,但由于简单的vtable父指针不适用于多重继承,逻辑上编译器无法通过该机制来完成:需要一些额外的支持数据结构,RTTI信息。

  

" 我想知道如何向下转换,然后检查它是否是指向正确类型的指针。但是,我无法修改所涉及的类或打开RTTI。

如果您无法更改代码或启用RTTI,则通常无法获取所需信息。

在您控制所有对象实例化的特殊情况下,您原则上可以维护一个单独的每对象类型信息映射,但效率极低。

答案 1 :(得分:0)

如果编译器在运行时插入足够的数据以使dynamic_cast工作,那么它们也会插入足够的RTTI来工作。如果您dynamic_cast可以引用其他类型,则可以检查它是否是同一类型或其他类型的后代。因此,这与在默认情况下简单地打开RTTI相同。

作为为什么编译器可能想要关闭它以提高效率的一个例子,如果你的派生类没有覆盖其父项的任何虚函数,会发生什么?编译器可能希望它只是重用相同的虚函数表。它也不需要跟踪基础和派生关系来进行函数调度。