C ++中基类对象和派生类对象的大小

时间:2014-11-19 02:16:47

标签: c++ inheritance

#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。

我有以下问题:

  1. 对于Base1类的大小,它应该包含一个vptr指向的 vtable和整数data1。为什么它的大小是16而sizeof(int) 在我的机器上是4。
  2. 对于派生类,它应该具有从Base1类继承的数据和一个额外的整数。它应该有更大的尺寸 比Base1类,为什么它们是一样的?
  3. 除了这些大小之外,Derived类中的vptr是什么? Derived类中的vptr是否会覆盖从Base1继承的vptr 类?

2 个答案:

答案 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