0

我从这里(2.6.2) 了解了 VTT 的结构。但是,我不明白所有元素的目的。

虚拟指针应该指向 D 的主虚拟表(在 vtable 组中,对吗?)

辅助 VTT包含在构造它们时赋予直接非虚拟基类(我们称它们为 B)的VTT 。我的理解是,因为这些直接基类(B)可能继承自虚拟类,所以这些直接基类(B)应该给这些已经初始化的虚拟类一些其他的 vtable,以“让他们相信”它们只是每个 B 的一部分。这个对吗?

现在,最后两种类型的条目的用途是什么:辅助虚拟指针虚拟 VTT?我知道继承层次结构中的虚拟类没有被赋予适当的最终 vtable,所以这可能是目的之一。此外,虚拟类可以从其他虚拟类继承自身(考虑 V1 继承自 V2)。然后 V2 再次需要一个特殊的 vtable 来“让它相信”它是 V1 的一部分(当 V1 正在构建时)。

如果您能解释VTT 中每种条目的确切内容和目的,我将不胜感激。

4

1 回答 1

0

Liskov 可替换性意味着派生类必须在基类可以接受的任何地方都可用。在 C++ 中,这意味着您可以将 Derived对象的地址传递给采用Base*.

现在,在构建复杂对象期间,您可能会遇到这样的情况,即*this根据 C++ 规则(因为Derivedctor 已成功运行)这样的 Derived 对象,因此您必须能够传递*this给期望Base*.

但是对于多重和虚拟继承,您需要额外的预防措施。Base*必须指向一个子Base对象。在 Itanium ABI 中,该基础子对象必须有一个 vtable 指针,该指针正确地描述了部分构造的对象的行为。这种行为完全取决于哪些部分是构造的,哪些不是构造的。

虽然可以部分构造对象,但其粒度只是类级别。调用的最派生构造函数确切地确定将运行哪些基类构造函数(这依赖于运行时行为)。这些中的每一个要么已经运行,要么没有运行。

因此,一个可行的实现是在每个基类子对象(可能重叠)中有一组虚表和一组虚表指针,并在每个构造函数成功完成时设置虚表指针。

虚拟基类与虚拟函数没有明显的关系,但由于您可以将虚拟基类偏移量存储在 vtables 中这一事实而得名。Derived* this当您传递给采用 的函数时,需要此偏移量Base*,其中该Base类型是 的虚拟基类Derived。(当它是常规基类时,您将使用固定偏移量,并且该偏移量甚至可以为零)

于 2017-06-09T12:51:02.720 回答