13

假设我们有以下程序:

class A
{     public:
      virtual fun(){};
};
class B:public A
{     public:
     virtual fun(){};
};
int main()
{
     A a1;
     B b1;
 }

我的问题是,当我们运行这个程序时,将创建多少个vtables和多少个?vptrs

4

6 回答 6

15

它严重依赖于实现,但通常每个具有任何虚函数的类都会得到一个 vtable 对象(没有虚函数或基的类不需要它们),每个具有 vtable 的类的对象一个 vptr(指向类的vtable)。

如果你有多重继承和虚拟基类,事情会变得更加复杂——这可以通过多种方式实现。一些实现对每个附加基类使用一个附加 vtable(因此最终每个类每个基类都有一个 vtable),而其他实现使用一个包含额外信息的单个 vtable。这可能导致每个对象需要多个 vptr。

B 中的virtual关键字无关紧要——如果函数在基类中是虚拟的,那么无论如何它在派生类中都是虚拟的。

于 2012-01-19T19:31:22.560 回答
14

该程序可以优化为与此程序完全相同:

int main(){}

所以,“无”是可能的。

于 2012-01-19T19:32:04.433 回答
9

基本上,2。一个用于class A,一个用于class B(vftables) 和 2 个 vfptrs,一个用于a1和一个用于b1.

但是,这不是标准强制要求,因此您也可以没有。(通常实现使用 vftables,但不是强制性的。

注意@R。Martinho Fernandes 进行了优化,您将不会创建任何对象,因此不会vfptrs.

于 2012-01-19T19:31:50.623 回答
6

请注意,这严格依赖于实现。
C++ 标准没有谈论vptror vtable,虚拟机制作为编译器的实现细节被遗漏了。所以实际上,编译器可以在不使用vptror的情况下实现它。vtable但是,几乎所有已知的编译器都使用vptrand来实现它vtable

鉴于上述情况,回答您的问题:

每个类都有自己的虚拟表。
而每个对象都有自己的虚拟指针。

于 2012-01-19T19:30:43.417 回答
4

仅当基类中存在至少 1 个虚拟函数时才会创建虚拟表,这将以任何方式继承到派生类。即使您从派生类 B 中删除 virtual 关键字也没关系,因为您已经在享受虚拟乐趣() 在 A. 所以虚拟表的数量将是 2(作为每个类的基础),虚拟 ptrs 的数量也将是 2,作为它的每个对象的基础。A---v_ptr* 的 VTABLE ,A::fun()

& VTABLE for B--- V_ptr*(从 A 继承),B::fun()/* B 可以访问 A::fun 和 B 的 fun(),但是因为我们提到了 A::fun()由于虚拟 B 的虚拟表充满了函数的最派生版本,fun(),它只不过是 B::fun()。希望这能消除你的疑问

于 2013-04-03T20:14:58.603 回答
1

将有 2 个vtables,一个用于A 类,一个用于B 类。并且将有 3 个vptrs,一个在 a1 中,两个在 b1 中(一个指向A 类vtable,另一个指向B 类)。vtable

于 2018-01-12T05:15:41.763 回答