5

根据我对 C++ 规范的(有限)知识,具有虚拟成员的类的 vtable 放置在第一个非纯非内联虚拟方法的定义中。编译器如何处理从具有所有纯虚拟方法(例如接口)的类继承的类?在这种情况下,vtable 放在哪里?

4

3 回答 3

6

vtable 存储实现的虚拟方法的地址。如果一个类的所有方法都是纯虚的并且没有实现,那么就不需要生成 vtable。

如果没有一些派生自它并实现方法的类,您将无法使用这样的类。每个实现了虚方法的类都有自己的单个虚表,其中包含所有虚方法的地址:它不以任何方式引用基类的虚表;地址重复。因此,如果您有一个从另一个类继承的类,那么该类将只使用它自己的 vtable。它不关心基类的vtable;这个 vtable 甚至不需要存在。

C++ 规范本身没有提到 vtables。它们只是一种已经变得普遍的编译器行为。

从 2020 年开始编辑:我差不多十年前写了这篇文章。我怀疑我是根据记忆和个人经验写的。下面的两条评论表明编译器确实为基类制作了 vtables(以抛出错误),尽管如果是这样,我不知道您将如何为它们构造一个对象,并且一些编译器确实重用了基类的 vtables。自 2011 年以来似乎没有人添加任何东西,而且我现在的认知能力有所下降,很难再想太多,所以如果这里的一些细节很重要,请自己做一些研究。

于 2011-01-06T18:12:18.543 回答
3

C++ 标准没有指定关于 vtable 放置的任何内容,甚至没有指定 v-table 的存在。它只是指定行为,而 v-table 恰好是最直接的实现,因此被广泛使用。

实际上,抽象类存在 v-table 的一个原因是在构造和销毁期间使用,此时对象的动态类型是抽象类。

在一个只有纯虚函数的类中,显然不可能有构造函数(因为构造函数不能是虚函数)。但是,析构函数当然可以是虚拟的。

您的类仍然可以有一个带有实现的纯虚拟析构函数,然后需要 v-table(或等效的实现细节)。

但是纯虚函数的实现很少见,并且在定义接口时不会这样做。

于 2011-01-06T18:31:19.113 回答
2

在您拥有实例之前,您不需要 vtable。

于 2011-01-06T18:06:25.923 回答