虚方法在没有RTTI的情况下工作,这不是意味着在运行时有足够的数据来确定它是哪个类吗?
(我想知道如何向下转换,然后检查它是否是指向正确类型的指针。我不能修改涉及的类,也不能打开RTTI。)
发布于 2018-02-16 00:17:36
虚函数调度不需要类型信息,即动态类型的标识。
虚拟函数分派通常通过每个对象中的vtable指针实现,其中该指针指向指向函数实现的特定类型的指针表( "vtable")。
dynamic_cast
和typeid
需要类型信息。
对于返回类型信息的typeid
,该信息必须存在于可执行文件中的某个位置。当您关闭信息的存储时,它将不会被检索到。但是dynamic_cast
呢?
在最简单的情况下,dynamic_cast
是从一些基类型引用到派生类型引用的向下转换,即D&
。派生类型不必是对象最派生的类型。因此,对于现在通用的用于动态分派的vtable方案,对象的vtable指针不需要指向D
类型的vtable,因此不能提供简单的成功检查。
对于被限制为单一继承的语言,通过使用vtable本身作为类型标识符,通过在vtable中的父指针向上搜索(单一)继承链,可以解决纯粹的向下转换的情况。
有了多重继承,事情就变得复杂了。例如,如果类Derived
继承自Base1
和Base2
,其中两者都是多态的,那么Derived
类的vtable不能简单地扩展Base1
的vtable和简单地扩展Base2
的vtable。因此,如果Derived
vtable扩展了Base1
,那么当一个代码重新解释为< Derived*
>d16时,指向对象的Derived
vtable指针将不再作为指向静态已知类的vtable的指针。
因此,一个后果是,在存在多重继承的情况下,转换为基类型引用并不总是简单地重新解释指针类型--指针值可能必须进行调整。
如何做到这一点并不明显,以至于Bjarne Stroustrup在向语言添加多重继承之前,必须向自己证明可以实现多重继承的vtable方案。
我不知道当前的编译器是如何处理它的,特别是对于dynamic_cast
,但由于简单的vtable父指针不能用于多重继承,所以从逻辑上讲,编译器不能通过这种机制做到这一点:需要一些额外的支持数据结构,RTTI信息。
"我想知道如何向下转换,然后检查它是否是指向正确类型的指针。但是,我不能修改相关的类或打开RTTI。
如果您不能更改代码或打开RTTI,您通常无法获得所需的信息。
在控制所有对象实例化的特殊情况下,原则上可以维护一个单独的每个对象的类型信息映射,但这将是非常低效的。
发布于 2018-02-16 00:33:49
如果编译器在运行时插入了足够的数据来使dynamic_cast
工作,那么它们也会插入足够的数据来使RTTI工作。如果您可以对另一个类型的引用执行dynamic_cast
操作,则可以检查它是同一类型还是另一个类型的后代。因此,这等同于在默认情况下简单地打开RTTI。
例如,为什么编译器可能想要关闭它以提高效率,如果您的派生类没有覆盖其父类的任何虚函数,会发生什么情况?编译器可能希望它简单地重用相同的虚拟函数表。它也不需要跟踪基础关系和派生关系来进行函数分派。
https://stackoverflow.com/questions/48818312
复制相似问题