多重继承的派生类中的Vptr
Vptr in derived class of Multiple Inheritance
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)
- 为什么使用 "this" 指针调用派生成员函数?
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 在派生函数中指定void*参数
- 如何通过派生类函数更改基类中的向量
- 如何委托派生类使用其父构造函数?
- 如何使用单独文件中的派生类访问友元函数对象
- 派生类销毁的最佳实践是什么
- 如何使用基类指针引用派生类成员
- 派生类是否可以在抽象工厂设计模式中具有数据成员
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何引用基类的派生类?
- 存储模板类型以强制转换回派生<T>
- 需要从 istream 和 ostream 派生 iostream
- 在 C++ 中用派生类型重写成员函数
- 具有多个类、派生类的C++正向声明
- 何时为派生类初始化 vptr?
- 如果派生类还具有基类中不存在的虚函数,则创建的 vptr 数
- 多重继承的派生类中的Vptr
- 当基类私有派生时,编译器插入的vptr是否变为私有
- 当派生类不重写虚函数时,为什么需要 vptr?