大话C++之:对象内存模型

  1. 一般继承(无虚函数覆盖)

    1. 只有一个虚指针,指向一个虚表,虚函数按顺序从祖先节点开始插入到虚表上。
    2. 字段按顺序从祖先节点开始插入到对象内存上
    3. 在这里插入图片描述
    4. 在这里插入图片描述
  2. 一般继承(有虚函数覆盖)

    1. 只有一个虚指针,指向一个虚表,虚函数按顺序从祖先节点开始,先查找是否有可以覆盖的,如果有,覆盖掉,否则插到最后。
    2. 字段按顺序从祖先节点开始插入到对象内存上
    3. 在这里插入图片描述
    4. 在这里插入图片描述
  3. 多重继承(有虚函数)

    1. 根据继承的类的数量来一一创建各自内存块,如继承了A,B,C三个类,则先后创建ABC三块,每一个均有自己的虚指针及字段,子类的虚函数分别遍历三个虚指针指向的虚表查找是否产生覆盖,如果有,则覆盖,如果没有则插入到在第一个父类的虚表里
    2. 每个类的字段按顺序跟在各个类内存块的虚指针后面。
    3. 在这里插入图片描述
    4. 在这里插入图片描述
  4. 重复继承(钻石模型)

    1. 此类型与多重继承类似,先把最底层的子类所继承的若干个间接父类(如B1, B2)当作一个整体,把它们先按单一继承创建,再根据多重继承的性质创建。

    2. 在这里插入图片描述

    3. 在这里插入图片描述

  5. 钻石型多重虚拟继承

    1. 	class B {……};
      	class B1 : virtual public B{……};
      	class B2 : virtual public B{……};
      	class D : public B1, public B2{ …… };
      
    2. 虚拟继承的就是为了解决重复继承中多个间接父类的问题。大体思想是:先从间接父类开始创建,把顶层的超类放在内存模型的最后,同时间接父类的虚表只能含有本身的虚函数(同时不能包含顶层超类的虚函数)和子类的虚函数。
    3. 间接父类每一个虚指针后紧一个vbptr虚基类表指针,变量指向一个全类共享的偏移量表,表中项目记录了对于该类而言,“虚基类表指针”与虚基类之间的偏移量。
    4. 内存模型创建过程:
      1. 先创建间接父类B1, 虚继承先创建虚指针,紧跟vbptr,接着是成员变量;遍历B1的虚函数,检查B类中是否有,如果有,则跳过;如果没有,则插入到函数表里。此时B1内存块为:vptr, vbptr, ib1, cb1; 虚函数表有:B1::f1, B1::Bf1;
      2. 重复上面步骤继续创建B2,此时内存块为:vptr, vbptr, ib1, cb1, vptr, vbptr, ib2, cb2; B2虚函数表有:B2::f2, B2::Bf2;
      3. 创建完间接父类,继而创建子类。把子类的字段按顺序紧放在内存后面,子类的函数在间接父类中接按顺序查找是否产生覆盖(同时不能包含顶层超类的虚函数),如果有,则覆盖,继续下一个函数。例如先遍历D::f,由于顶层超类包含了,跳过不处理;对于D::f1,在B1的虚函数表里找到了,则覆盖,此时B1的虚函数表为:D::f1, B1::Bf1。对于D::f2,覆盖了B2的B::f2,B2虚函数表有:D::f2, B2::Bf2; 对于D::Df,没有找到覆盖的,则插到第一个间接父类的虚函数表里。此时B1的虚函数表为:D::f1, B1::Bf1,D::Df。
      4. 最后创建顶层超类。按常规创建B类,创建完之后,用D类的虚函数遍历检查是否产生覆盖,如果有,则覆盖,否则跳过。
    5. 在这里插入图片描述
    6. 在这里插入图片描述

    参考内容:
    钻石型继承模型的内存分布
    C++ 对象的内存布局

  • 14
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值