C++虚拟继承解决数据冗余和二义性的原理

devtools/2024/10/20 13:46:21/

关于什么是继承、什么是菱形继承以及菱形虚拟继承的问题大家可以参考我的上一篇博文C++入门11——详解C++继承(菱形继承及菱形虚拟继承),此篇文章我们重点探究虚拟继承解决数据冗余和二义性的原理。


首先我们先来看正常的菱形继承:

class A
{
public:int _a;
};class B:public A
{
public:int _b;
};class C :public A
{
public:int _c;
};class D :public B, public C
{
public:int _d;
};int main()
{D d;d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}

打开内存窗口,观察d对象:

从内存窗口可以看到d对象存在两个_a,造成了数据的冗余。


接下来看一下菱形虚拟继承:

class A
{
public:int _a;
};class B :virtual public A
{
public:int _b;
};class C :virtual public A
{
public:int _c;
};class D :public B, public C
{
public:int _d;
};int main()
{D d;d.B::_a = 1;d.C::_a = 2;d._b = 3;d._c = 4;d._d = 5;return 0;
}

打开内存窗口,观察d对象:

从中可以看出_a非但没有出现两次,反而跑到了对象组成的最下面,A类中的_a同时属于B类和C类,可是我B类和C类需要用到_a时,如何去寻找公共的_a呢?

仔细查看,虚拟继承与非虚拟继承的内存窗口对比,前者的B类与C类不但没有存_a,反而存了一个类似地址的数据,它存个这玩意干嘛呢?

既然那么像地址,那我们再调出一个内存窗口,分别查看这两个类似地址的数据到底指向何方:

 

发现B里面存的地址指向的数据为14(即20),C里面存的地址指向的数据为0c(即12)。

这两个数据是干嘛的呢?它存这样一个数据有何用途?

盲猜一波:

既然B类的第一行存的地址指向了14,那我就让这个地址+14,C也是同样的道理,让C里面的地址+0c:

结果两个不同的等式相加得到了相同的答案——93F9A0!

回头看,93F9A0正是_a的地址啊!


所以我们不得不得出一个结论:

这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。 

图示: 

 


很多人说C++语法复杂,其实多继承就是一个体现,多继承也可以认为是C++的缺陷之一。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂,知道了虚拟继承解决数据冗余和二义性的原理似乎更加印证了这些说法。所以一般不建议设计出多继承,一定不要设计出菱形继承。否则在复杂度及性能上都有问题。


http://www.ppmy.cn/devtools/111307.html

相关文章

Vue使用query传参Boolean类型,刷新之后转换为String问题

做项目时发现第一次进入页面时传参是正常的Boolean类型,刷新之后变成了String,这是浏览器进行的一次强制转换; vue-router 传参,不管是 params 形式还是query形式传参,在页面刷新后,params 和 query 对象中…

力扣--649.Dota2参议院

Dota2 的世界里有两个阵营:Radiant(天辉)和 Dire(夜魇) Dota2 参议院由来自两派的参议员组成。现在参议院希望对一个 Dota2 游戏里的改变作出决定。他们以一个基于轮为过程的投票进行。在每一轮中,每一位参…

ElementUI2.x El-Select组件 处理使用远程查找时下拉箭头丢失问题

1、问题描述 elementui2.x版本使用el-select组件的remote-method远程查找时&#xff0c;发现下拉箭头丢失了&#xff0c;且当查找接口返回数据为空时&#xff0c;也不会展开下拉列表来显示暂无数据提示&#xff1b; 2、源码解析 官网使用示例&#xff1a; <template>…

鱼类检测-目标检测数据集(包括VOC格式、YOLO格式)

鱼类检测-目标检测数据集&#xff08;包括VOC格式、YOLO格式&#xff09; 数据集&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1B4o8IgOmAWeQJDWpJWxqXg?pwdjaco 提取码&#xff1a;jaco 数据集信息介绍&#xff1a; 共有 2848 张图像和一一对应的标注文件 标注文…

机器学习:逻辑回归--过采样

目录 前言 一、为什么使用过采样&#xff1f; 二、代码实现 1.完整代码 2.数据预处理 3.进行过采样 4.建立模型 5.绘制混淆矩阵 总结 前言 过采样&#xff08;Oversampling&#xff09;是指在数据处理或机器学习中&#xff0c;增加少数类样本的数量以平衡类别分布。常…

图片详解,最简单易懂!!!Ubuntu增强功能

文章目录 共享粘贴板共享文件夹vim 共享粘贴板 双击 输入认证用户密码 显示这个界面 命令行界面 reboot就会重新启动 虚拟机 设置下面的选项&#xff0c;就可以实现共享粘贴 共享文件夹 先在本机&#xff08;windows&#xff09;新建一个共享文件夹 再在ubuntu建一个共…

Web日志分析工具GoAccess

目录 1. 介绍 2. 功能 3. 支持的格式 4. 安装 从发布版本构建 从GitHub构建&#xff08;开发&#xff09; 命令行安装 5. 使用 5.1 监视Apache日志 5.2 通过web仪表板查看日志 浏览器访问 5.3 汉化设置 测试访问 1. 介绍 GoAccess是一个开源的实时网络日志分析器和…

Axure设计之全屏与退出全屏交互实现

在Axure RP中&#xff0c;设计全屏与退出全屏的交互功能可以极大地提升用户体验&#xff0c;尤其是在展示产品原型或进行演示时。本文将详细介绍如何在Axure RP中通过结合JavaScript代码实现全屏与退出全屏的交互效果。 ​ Axure原型设计web端交互元件库&#xff1a;https://…