#include <stdio.h>
class Base1
{
public:
virtual int virt1() { return 100; }
int data1;
};
class Derived : public Base1
{
public:
virtual int virt1() { return 150; }
int derivedData;
};
int Global1( Base1 * b1 )
{
return b1->virt1();
}
main1()
{
Derived * d = new Derived;
printf( "%d %d\n", d->virt1(), Global1( d ));
printf("size: Base1:%d\n", sizeof(Base1));
printf("size: Derived:%d\n", sizeof(Derived));
}
我使用上面的代码打印出基类和派生类的大小。我在64位机器上运行代码。我电脑的输出是
150 150
size: Base1:16
size: Derived:16
我还尝试使用sizeof(int)打印出int的大小,它是4。
我有以下问题:
答案 0 :(得分:3)
对于Base1类的大小,它应包含指向vtable的vptr和一个整数data1。为什么它的大小是16而sizeof(int)在我的机器中是4。
填充以确保Base1
s必须连续的†数组中的8字节指针正确对齐。
†C ++标准要求数组元素在内存中是连续的,并计算索引 i 的元素的内存地址,并计算数组的基地址加上 i 的次数。元素大小
对于派生类,它应该具有从Base1类继承的数据和一个额外的整数。它应该比Base1类更大,为什么它们是相同的?
已为额外的int
成员收回填充内容。您可以输出d
,&d->data1
,&d->derivedData
。
除了这些大小之外,Derived类中的vptr是什么? Derived类中的vptr是否会覆盖从Base1类继承的vptr?
在使用指向虚拟调度表的指针(我知道的每个编译器,但它不是C ++标准强制要求)的实现中,Derived
类构造函数和析构函数会覆盖“vptr” - 前者的写作构造函数体运行后指向Derived
的VDT 的指针,后者在析构函数体运行之前恢复指向Base
VDT 的指针(这可以确保您不会在其正式生命周期之前或之后调用对象上的Derived
成员函数。)
答案 1 :(得分:0)
有许多因素决定了C ++中对象的大小。
这些因素是:
当我在MVSC 2010上编译代码时,x64位。这是内存布局的结果:
class Base1 size(16):
+---
0 | {vfptr}
8 | data1
| <alignment member> (size=4)
+---
Base1::$vftable@:
| &Base1_meta
| 0
0 | &Base1::virt1
Base1 :: virt1这个调整器:0
class Derived size(24):
+---
| +--- (base class Base1)
0 | | {vfptr}
8 | | data1
| | <alignment member> (size=4)
| +---
16 | derivedData
| <alignment member> (size=4)
+---
Derived::$vftable@:
| &Derived_meta
| 0
0 | &Derived::virt1
您应该阅读有关vTable,虚函数,类/结构的字节对齐的更多信息。 在这里,一些链接可以帮助您。希望对您有所帮助:
确定类对象的大小:http://www.cprogramming.com/tutorial/size_of_class_object.html
内存布局:http://www.phpcompiler.org/articles/virtualinheritance.html