假设我们有以下程序:
class A
{ public:
virtual fun(){};
};
class B:public A
{ public:
virtual fun(){};
};
int main()
{
A a1;
B b1;
}
我的问题是,当我们运行这个程序时,将创建多少个vtables
和多少个?vptrs
它严重依赖于实现,但通常每个具有任何虚函数的类都会得到一个 vtable 对象(没有虚函数或基的类不需要它们),每个具有 vtable 的类的对象一个 vptr(指向类的vtable)。
如果你有多重继承和虚拟基类,事情会变得更加复杂——这可以通过多种方式实现。一些实现对每个附加基类使用一个附加 vtable(因此最终每个类每个基类都有一个 vtable),而其他实现使用一个包含额外信息的单个 vtable。这可能导致每个对象需要多个 vptr。
B 中的virtual
关键字无关紧要——如果函数在基类中是虚拟的,那么无论如何它在派生类中都是虚拟的。
该程序可以优化为与此程序完全相同:
int main(){}
所以,“无”是可能的。
基本上,2。一个用于class A
,一个用于class B
(vftables) 和 2 个 vfptrs,一个用于a1
和一个用于b1
.
但是,这不是标准强制要求,因此您也可以没有。(通常实现使用 vftables,但不是强制性的。
注意@R。Martinho Fernandes 进行了优化,您将不会创建任何对象,因此不会vfptrs
.
请注意,这严格依赖于实现。
C++ 标准没有谈论vptr
or vtable
,虚拟机制作为编译器的实现细节被遗漏了。所以实际上,编译器可以在不使用vptr
or的情况下实现它。vtable
但是,几乎所有已知的编译器都使用vptr
and来实现它vtable
。
鉴于上述情况,回答您的问题:
每个类都有自己的虚拟表。
而每个对象都有自己的虚拟指针。
仅当基类中存在至少 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()。希望这能消除你的疑问
将有 2 个vtables
,一个用于A 类,一个用于B 类。并且将有 3 个vptrs
,一个在 a1 中,两个在 b1 中(一个指向A 类vtable
,另一个指向B 类)。vtable