【发布时间】:2012-02-14 11:09:31
【问题描述】:
假设我们有以下程序:
class A
{ public:
virtual fun(){};
};
class B:public A
{ public:
virtual fun(){};
};
int main()
{
A a1;
B b1;
}
我的问题是,当我们运行这个程序时,将创建多少个vtables 和多少个vptrs?
【问题讨论】:
假设我们有以下程序:
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 或vtable,虚拟机制作为编译器的实现细节被忽略了。所以实际上,编译器可以在不使用vptr 或vtable 的情况下实现它。然而,几乎所有已知的编译器都使用vptr 和vtable 来实现它。
鉴于以上情况,回答您的问题:
每个类都有自己的虚拟表。
而每个对象都有自己的虚拟指针。
【讨论】:
只有在基类中至少有 1 个虚函数时才会创建虚拟表,这将通过任何方式继承到派生类。即使你从派生类 B 中删除 virtual 关键字也没关系,因为你已经拥有A 中的一个虚拟 fun()。 因此,虚拟表的数量将是 2(作为每个类的基础),虚拟 ptr 的数量也将是 2,作为它的每个对象的基础。 VTABLE for A---v_ptr* ,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 )。
【讨论】: