在C++中,子类和父类的内存分布情况取决于继承的方式(单继承、多继承、虚继承)以及类中是否包含虚函数。以下是几种常见的内存分布情况的详细说明:

单继承

父类和子类的内存布局

  1. 子类对象的内存布局是父类成员变量和子类成员变量的连续排列

  2. 如果父类中有虚函数,则子类对象中包含一个指向虚函数表(vtable)的指针(vptr),用于支持多态。

内存分布示例

1
2
3
4
5
6
7
8
9
10
class Base {
public:
int a;
virtual void func() {} // 虚函数
};

class Derived : public Base {
public:
int b;
}
  1. Base类的内存布局:vptr(4或8字节,取决于平台)+a(4字节)
  2. Derived类的内存布局:vptr(与Base共享)+a(从Base继承)+b(4字节)

多继承

父类和子类的内存布局

  1. 子类对象的内存布局是多个父类成员变量的连续排列,加上子类自己的成员变量。
  2. 每个父类如果有虚函数,子类对象中会包含多个虚函数表指针(vptr)。

内存分布示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Base1 {
public:
int a;
virtual void func1() {} // 虚函数
};

class Base2 {
public:
int b;
virtual void func2() {} // 虚函数
};

class Derived : public Base1, public Base2 {
public:
int c;
};

Derived类的内存布局

  1. Base1的vptr+a(4字节)
  2. Base2的vptr+b(4字节)
  3. c(4字节)

虚继承

父类和子类的内存布局

  1. 虚继承用于解决多继承中的重复继承问题(如菱形继承)。
  2. 子类对象中会包含一个指向虚基类的指针(称为需基类指针,vptr),用于定位虚基类的成员变量。

内存分布示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Base {
public:
int a;
};

class Derived1 : virtual public Base {
public:
int b;
};

class Derived2 : virtual public Base {
int c;
};

class Final : public Derived1, public Derived2 {
public:
int d;
};
  1. Derived1的内存布局:
    虚继承指针(vptr)+ b(4字节)。
    虚基类Base的成员变量a是单独存储的,不直接嵌入到Derived1中。
  2. Derived2的内存布局类似Derived1。
  3. Final类的内存布局:
    Derived1 的虚继承指针 + b。
    Derived2 的虚继承指针 + c。
    虚基类Base的成员变量a(共享)。
    d(4字节)

内存对齐

在C++中, 编译器会对类的成员变量进行内存对齐,以提高访问效率。
内存对齐可能导致类的大小大于成员变量实际占用的大小。

示例

1
2
3
4
5
class Example {
public:
char c; // 1 字节
int a; // 4 字节
};

实际内存大小可能是8字节(1字节的c+3字节的填充+4字节的a)