[c++]菱形继承解析

菱形继承

  • 大概示意图:

菱形继承不一定只是标准的菱形,只要形似菱形的都可以叫菱形继承。


(以下说明都是默认公有继承,public和protected成员情况下)

菱形继承会造成数据的冗余和二义性:

  • 冗余:一个Assitant对象里面有两个Person的成员(如果成员是_name,那么就会有两个_name)
  • 二义性:如果用Assitant对象取访问_name,会报错(编译器不确定访问哪一个_name

为了处理这种情况,祖先就开发并使用了虚继承

  • 我们使用更简便的例子取讲解虚继承具体是怎么取处理的:

虚拟继承之后发现: _a 变成唯一的了,并且将_a放在了D对象组成的最下面

这时候有小伙伴就会问了,那编译器怎么取访问_a呢?而且75c和764(上图中地址的后缀)存放的又是什么呢?

  • 75c和764里面的指针就是编译器找到那个唯一_a的途径 ;75c存放的地址位置指向一个叫虚基表的东西,所以B和C中存放对应地址 的指针就叫虚基表指针;
  • 虚基表里面存放着一种叫偏移量的东西,简单来说:偏移量里面第二行存放的是,当前指针(虚基表指针 )与对象底部_a之间的地址距离。[1](#当前指针(虚基表指针)与对象底部_a之间的地址距离。1)

简图解释如下: (便于和上面相通,读者们可将A和Person视作同一个类)
到这里有同学可能就会提问:那如果A(Person)里有更多的成员变量呢?那是不是虚基表里面会存更多的偏移量?

  • 事实上并不会哦,只需要存储A类型中首个声名的成员变量的偏移量即可,找到首个后,编译器自然就会向下访问下面的成员变量。

**有同学可能会问,为什么使用虚拟继承之后,对象内占用的空间变多了? **

  • 实际上这是因为A类太小了造成的错觉,加入A类中的成员函数增加到更多个,那么再虚拟后占用就会就会清晰可见的减少:
  • 证明多个成员变量都是存在对象的底部:

  1. 75c到_a(所继承A的首个成员地址)的地址770之间差了20 (16进制下是显示的是14 ) ↩︎
相关推荐
hnjzsyjyj4 小时前
东方博宜OJ 2190:树的重心 ← 邻接表 or 链式前向星
数据结构·链式前向星·树的重心
ChoSeitaku6 小时前
NO15数据结构选择题考点|线性表|栈和队列|串
数据结构
醇氧6 小时前
【Windows】优雅启动:解析一个 Java 服务的后台启动脚本
java·开发语言·windows
hetao17338376 小时前
2025-12-12~14 hetao1733837的刷题笔记
数据结构·c++·笔记·算法
椰子今天很可爱7 小时前
五种I/O模型与多路转接
linux·c语言·c++
一直都在5727 小时前
数据结构入门:时间复杂度与排序和查找
数据结构
MapGIS技术支持7 小时前
MapGIS Objects Java计算一个三维点到平面的距离
java·开发语言·平面·制图·mapgis
程序员zgh7 小时前
C++ 互斥锁、读写锁、原子操作、条件变量
c语言·开发语言·jvm·c++
小灰灰搞电子7 小时前
Qt 重写QRadioButton实现动态radioButton源码分享
开发语言·qt·命令模式
by__csdn7 小时前
Vue3 setup()函数终极攻略:从入门到精通
开发语言·前端·javascript·vue.js·性能优化·typescript·ecmascript