[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 ) ↩︎
相关推荐
Just right14 小时前
python安装包问题
开发语言·python
dxz_tust14 小时前
flow match简单直观理解
开发语言·python·深度学习·扩散模型·流匹配·flow match
写代码的【黑咖啡】14 小时前
Python 中的时间序列特征自动提取工具:tsfresh
开发语言·python
_OP_CHEN14 小时前
【算法基础篇】(五十一)组合数学入门:核心概念 + 4 种求组合数方法,带你快速熟悉组合问题!
c++·算法·蓝桥杯·排列组合·组合数学·组合数·acm/icpc
Frank学习路上14 小时前
【Qt】问题记录ld: framework ‘AGL‘ not found on MacOS 26
开发语言·qt·macos
漫随流水14 小时前
leetcode回溯算法(491.非递减子序列)
数据结构·算法·leetcode·回溯算法
陳103014 小时前
C++:二叉搜索树
开发语言·数据结构·c++
wqwqweee14 小时前
Flutter for OpenHarmony 看书管理记录App实战:个人中心实现
开发语言·javascript·python·flutter·harmonyos
楼田莉子14 小时前
Linux进程间通信——管道
linux·运维·服务器·c++·学习
t1987512814 小时前
水下无人自主航行器(AUV)的MATLAB/Simulink仿真程序实现
开发语言·matlab