多继承与虚继承内存布局

class a {int data_a;};
class va : virtual public a {int data_va;};
class va2 : virtual public a {int data_va2;};
class b : public a {int data_b;};
class b2 : public a{int data_b2;};
class child : 
  virtual public va, 
  virtual public b, 
  public va2, 
  public b2 {int data_child;};

内存布局:
1、布局中先实继承类,再子类成员,再虚继承类
2、虚继承的类只实例化一个内存
3、实继承的类,分别实例化一个内存
4、虚继承的类会深度遍历添加虚爷类的内存,且只添加一次,后面用到这个虚爷类时可直接复用
5、子类的虚表与第一个实基类合并,如果没有实基类,则加一个子类的虚表
6、实例化顺序与内存布局不同,是按写的顺序来的,本例中顺序为:va::a() -> va() -> b()::a() -> b() -> va2() -> b2::a() -> b2() 其中va2的构造不需要再调一次a的构造,因为虚类只有一个。

/** 实继承虚基类 */
*vtbl_va2 
data_va2
// 这里没有va2::a 的 data_a 因为是虚继承的a类
// 虚类a只有一个,它会在深度遍历virtual继承类va时添加在va后面。
/** 实继承实基类 */
*vtbl_b2 
b2::a::data_a // b2实继承的a,所以先有a的成员再有b2的成员
data_b2
// 子类成员
data_child
/** 虚继承虚基类 */
*vtbl_va
data_va
// 虚继承深度遍历找到虚基基类a,放在这后面
*vtbl_a
data_a
/** 虚继承实基类 */
*vtbl_b
b::a::data_a
data_b

虚表的特点:
1、虚表位置-16为本基类相对子类(无论父还是爷,都是相对子类)的this指针偏移。
2、虚表位置-8指向子类(无论父还是爷,都是其子类)的typeinfo所在位置(即typeid(class)的返回地址)。
3、子类会修改所有基类(以及爷类)的虚表中重写了的虚函数的指针。
4、子类的虚表与第一个实继承类的虚表合并,没有实继承类时,单独创建一个虚表在最顶部。

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值