此文针对C++多种继承方式下的内存分布结构进行一系列验证!若有错误,感激指正!
由于此文的重点在于内存分布,简便起见,所以没有对内存对齐进行详细的阐明。
工具
- visual studio 2019 (64位)
预备工作
- 第一步
右键你的源文件,选择“属性”,弹出第二步所示的对话框。 - 第二步
选择“命令行”,并在右边的“其他选项”中输入如下格式:
/d1 reportAllClassLayout,它可以看到所有相关类的内存布局;
若写/d1 reportSingleClassLayoutXXX(XXX为类名),则只会打出指定类XXX的内存布局。
正式工作
共分为单继承,多重继承,菱形继承三种情况,每种情况会进行细分。
- 首先展示的是一个基类
class Base1 {
public:
int Base1_a;
virtual void myfunc1() {
cout << "I am Base1" << endl; };
};
它的对应内存结构如下图:
根据上图可知,在Base1基类中,有一个int型Base1_a变量和一个虚函数表指针,在该编译器中,虚函数表指针被放在起始处。前面的对应数字表示对应变量相对于起始处的偏移量。再观察上图下方的虚函数表,第一个0表示该虚函数表相对于起始处的偏移量,第二个0表示虚函数表中虚函数的索引号。可见,虚函数表中只有一个虚函数myfunc1,符合事实。
- 接下来,我们定义一个派生类
一、单继承
分3种情况
- 没有虚函数
class Derived :public Base1 {
public:
int Derived_a;
};
它的对应内存结构如下图:
由上图可以看到,虚表指针被继承了,且仍位于内存分布的起始处,接着是基类的成员变量Base1_a,最后是子类的成员变量Derived_a。再观察上图下方的虚函数表,由于派生类并没有任何虚函数,故直接继承基类的虚函数表。
- 重写基类的虚函数
class Derived :public Base1 {