[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 ) ↩︎
相关推荐
我材不敲代码30 分钟前
Python实现打包贪吃蛇游戏
开发语言·python·游戏
身如柳絮随风扬1 小时前
Java中的CAS机制详解
java·开发语言
-dzk-3 小时前
【代码随想录】LC 59.螺旋矩阵 II
c++·线性代数·算法·矩阵·模拟
韩立学长3 小时前
【开题答辩实录分享】以《基于Python的大学超市仓储信息管理系统的设计与实现》为例进行选题答辩实录分享
开发语言·python
froginwe113 小时前
Scala 循环
开发语言
m0_706653233 小时前
C++编译期数组操作
开发语言·c++·算法
故事和你914 小时前
sdut-Java面向对象-06 继承和多态、抽象类和接口(函数题:10-18题)
java·开发语言·算法·面向对象·基础语法·继承和多态·抽象类和接口
Bruk.Liu4 小时前
(LangChain实战2):LangChain消息(message)的使用
开发语言·langchain
qq_423233904 小时前
C++与Python混合编程实战
开发语言·c++·算法
m0_715575344 小时前
分布式任务调度系统
开发语言·c++·算法