【问题标题】:C++ - TC++PL RTTI dynamic_cast downcasting and virtual table confusion (as well as in its implementation)C++ - TC++PL RTTI dynamic_cast downcasting 和 virtual table 混淆(以及它的实现)
【发布时间】:2016-12-03 11:01:06
【问题描述】:

我正在阅读 B. Stroustrup 的“The C++ Programming Language (4th Edition)”中的 RTTI。英语不是我的第一语言,我不确定我是否从它使用dynamic_cast<T*>(p) 对向下转换机制的解释中得出了正确的结论。我引用了书中的文字

要求指针的类型是多态的可以简化 dynamic_cast 的实现,因为它可以很容易地找到 存放有关对象类型的必要信息的地方。一种 典型的实现会附加一个“类型信息对象” (第 22.5 节)通过将指向类型信息的指针指向对象 对象类的虚函数表(§3.2.3)。为了 例子: 虚线箭头表示允许开始的偏移量 仅给定一个指向多态的指针即可找到完整的对象 子对象。很明显,dynamic_cast 可以有效地 实施的。所涉及的只是对 type_info 的一些比较 表示基类的对象;没有昂贵的查找或字符串 需要比较。

我的困惑来自 “虚线箭头表示一个偏移量,它允许在给定的情况下找到完整对象的开始 只是一个指向多态子对象的指针。”

我从这一行的推论是:

  • vtbl(虚函数表)中存储有指向基(或子对象)的指针,虚线表示指向子对象的指针

  • 这与该行的第二部分相矛盾,即 只给出一个指向多态子对象的指针。但这会造成更多的混乱,我们如何将指针传递给子对象。在向下转换时,我们在 括号中传递派生类名称 T,在 ()p 的指针/strong> dynamic_cast<T*>(p) 语法的括号。

如果我的第一点是合理的或被认为是正确的,则作为一个完整的过程。 那么我们可以说我的以下假设成立吗?

假设 :: 在向下转换时,虚拟函数表 (vtbl) 中存在的指针所指向的类型信息对象 (type_info) 会与基类的 type_id 连续进行比较。如果在前面提到的比较中找到p(或p指向的对象)的type_id,则创建派生类的对象。由于指向子对象的指针存储在虚拟表中,我们将我们从 p (这是dynamic_cast<T*>(p) 的输入参数)获得的基类对象 memcpy(或类似的东西)到驱动类的子对象(我们从虚函数表中的指针中找到)。

我已经对此进行了谷歌搜索,但没有找到任何可能的解释。如果我跑题了,请引导我到正确的 StackExchange 模块。

P.S : 在旁注中,主题 3.2.3 解释书中的虚拟表。以线条结尾。

这种虚拟调用机制几乎可以像 “正常函数调用”机制(25%以内)。

这里的 25% 以内是什么意思。再次,我对此有我的假设,但如果有人向我陈述他们的结论会更好。

最后,任何关于如何通过 dynamic_cast 识别或实现交叉转换的信息将不胜感激。

【问题讨论】:

    标签: c++ internal


    【解决方案1】:

    没有进行复制,因为所有对象(子对象)一直都存在。可能有几个基类,其中一些可能具有虚拟继承。

    vtables 中的指针(可能存储为偏移量,而不是固定地址)是帮助运行时查找不同子对象在整个对象中的起始位置的一种方法。或者从指向子对象的指针中找到完整对象的开始。显然,只有第一个基类可以定位在对象的开头,其他的必须定位为start + offset

    虚拟调用几乎与直接函数调用一样有效。在机器代码级别,函数调用只是编码为call address_of_function,地址存储在指令内部。

    虚拟调用可以实现为call *(vtable + offset)。如果 vtable 地址存储在寄存器中,则许多 CPU 都支持在单个指令中执行此间接操作。代价是获取真实函数地址的额外内存访问。如果该函数做了什么重要的事情,这种额外的内存访问不会有太大的不同。

    【讨论】:

      猜你喜欢
      • 2011-05-11
      • 1970-01-01
      • 2019-12-08
      • 1970-01-01
      • 2011-12-02
      • 1970-01-01
      • 2021-12-23
      • 1970-01-01
      • 2012-03-19
      相关资源
      最近更新 更多