多重继承的派生类中的Vptr

Vptr in derived class of Multiple Inheritance

本文关键字:Vptr 派生 多重继承      更新时间:2023-10-16
class A
{
public:
virtual void f()
{}
};
class B 
{
public:
virtual void g()
{}
};
class C : public A,public B
{
};

int main()
{
A a;
B b;
C c;
cout << sizeof(a) << endl;
cout << sizeof(b) << endl;
cout << sizeof(c) << endl;
return 0;
}

为什么c的大小是8。但我认为它的大小应该是12,因为vptr存在于其中。请解释vptr是否存在于c中。

虽然任何自定义类型的大小都取决于编译器,并且可以随新编译器、新操作系统或无任何原因而更改,但了解它的来源以及通常影响类型大小的因素是很有用的。

任何分析都将基于特定的实现,所以我将在Linux上使用g++。给出了3个classess(我在C中添加了另一个虚拟函数以获得更多见解),以64位模式编译,我看到了以下大小:

sizeof(A)sizeof(B)=8、sizeof(C)=16。这些尺寸是从哪里来的?

CCD_ 4和CCD_。它们非常相似,并且没有任何数据成员。但是,它们确实具有virtual功能。g++中的虚拟函数是通过虚拟函数表实现的,类的每个实例都有一个指向它的指针。在64位系统中,指针是8字节,所以这两个类的大小都是8。

现在,学习C。它的尺寸是什么?人们可能会期望它是24,对吧?8字节表示A的vptr,8字节表示B的vptr和8字节表示C的vptr。但如果你仔细想想,我们实际上并不需要单独的vptr表示C。相反,我们可以用A的方法创建一个虚拟表,向其中添加我们的虚拟函数,并使用指向这个新表的指针。因此,我们不需要额外的指针!我们仍然需要一个指向B表的单独指针,这样当转换为B时,对象的行为才会正确。

这完全取决于实现。编译器根本不必使用vptr来实现虚拟类。

但是,在您的示例中,C对象和A子对象共享一个vptr,而B子对象有自己的vptr。两者都是指针大小,在您的实现中是4。

如前所述。Standard根本没有指定虚拟指针。而且它完全依赖于实现。

您的编译器是32位的,指针大小为4字节。所以A的尺寸是4。B的尺码是4号。

现在C有两个vptr。一个来自类A,另一个来自B。它可以使用父类中的vpty。现在,即使定义了一个新的虚拟方法,它也会重用父对象的一个指针。(在gcc4.8的情况下,它的A的vptr将用作C的vptr)