C++ 对象的内存布局理解
以下是我看完陈皓的C++对象的内存布局后的一些理解
普通继承
- 单一继承(A->B, B->C)
- 虚函数表在最前面
- 被重载的虚函数得到更新,未重载的虚函数按照声明和继承顺序排在后面
- 数据成员在虚函数表后面,按照声明和继承顺序排在后面
- 多重继承((A,B,C)->D)
- 每个父类都有自己的虚表,虚表后面是父类的数据成员,子类成员在所有父类内存布局(虚表+数据成员)后面
- 父类内存布局(虚表+数据成员)按照继承声明顺序排列,如(虚表A,数据成员A,虚表B,数据成员B,虚表C,数据成员C)
- 每个父类虚表中被重载的函数得到更新,子类的未重载虚函数放入第一个父类的虚表中,跟在父类的虚函数后面。
- 棱形继承(B->B1, B->B2, (B1,B2)->D)
- 每个父类都有自己的虚表,虚表后面是父类的数据成员,子类成员在所有父类内存布局(虚表+数据成员)后面
- 父类内存布局(虚表+数据成员)按照继承声明顺序排列,如(虚表A,数据成员A,虚表B,数据成员B,虚表C,数据成员C)
- 每个父类虚表中被重载的函数得到更新,子类的未重载虚函数放入第一个父类的虚表中,跟在父类的虚函数后面。
- 每个父类(类B1或类B2)的内存布局(虚表+数据尘缘)中都有其上一级父类(类B)的拷贝(类B未重载的虚函数和数据成员),因此类D中有类B的两份拷贝(会产生二义性)。
- 单一继承(A->B, B->C)
虚拟继承
- 单一继承(B->B1)
- B1拥有自己的虚表
- B1的内存布局在B的前面(B1虚表,B1数据成员,B虚表,B数据成员)
- B的虚表中被重载的虚函数得到更新
- 棱形继承
class B {……};
class B1 : virtual public B{……};
class B2: virtual public B{……};
class D : public B1, public B2{ …… };
- 每个父类都有自己的虚表,虚表后面是父类的数据成员,子类成员在所有父类内存布局(虚表+数据成员)后面,最后是上一级父类(类B)的内存布局
- 父类内存布局按照继承声明顺序排列
- 每个父类(包括上一级父类B)虚表中被重载的函数得到更新,子类的未重载虚函数放入第一个父类的虚表中,跟在父类的虚函数后面。
- 单一继承(B->B1)