C++三大特性—继承“复杂的菱形继承及菱形虚拟继承”

C++的一个大坑:菱形继承 希望这篇文章能让你理解什么是菱形继承,以及菱形继承的注意事项


单继承与多继承

单继承:一个子类只有一个直接父类时称这个继承关系为单继承
在这里插入图片描述

多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承
在这里插入图片描述
java语言不支持多继承,只支持单继承。

菱形继承:菱形继承是多继承的一种特殊情况
在这里插入图片描述


菱形继承会导致什么呢?

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。在Child的对象中Person成员会有两份

比如:

class Person
{
public:
	string _name; // 姓名
};
class Student : public Person
{
protected:
	int _num; //学号
};
class Teacher : public Person
{
protected:
	int _id; // 职工编号
};
class Child : public Student, public Teacher
{
protected:
	string _obj; // 主修项目
};

在这里插入图片描述

	Child obj;
	obj._name;
	//从空间上说是数据冗余、从访问角度上是二义性

运行结果是:在这里插入图片描述
如果想要代码跑起来可以这样:指定类域去访问

	Child obj;
	obj.Student::_name = "张三";
	obj.Teacher::_name="张老师";

在这里插入图片描述


虚拟继承

但是上述做法从根本上并没有解决数据二义性的问题,为了能够解决二义性,C++又引入了一个坑,虚拟继承。(在继承的类派生列表的访问说明符前加上virtual)

class Person
{
public:
	string _name; // 姓名
};
class Student : virtual public Person
{
protected:
	int _num; //学号
};
class Teacher : virtual public Person
{
protected:
	int _id; // 职工编号
};
class Child : public Student, public Teacher
{
protected:
	string _obj; // 主修项目
};

在这里插入图片描述

  虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和Teacher的继承Person时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要在其他地方去使用

  为了更清楚的明白菱形继承与菱形虚拟继承的关系,我们通过使用内存监视窗口来了解其数据存储方式(监视窗口编译器优化过,不是原汁原味了):
在这里插入图片描述

class A
{
public:
	int _a;
};
class B :  public A
//class B : virtual public A
{
public:
	int _b;
};
class C :  public A
//class C : virtual public A
{
public:
	int _c;
};
class D : public B, public C
{
public:
	int _d;
};

我们先使用内存窗口观察菱形继承在内存中的存储状况:

	D d;
	d._b = 1;
	d._c = 2;
	d._d = 3;
	d.B::_a = 4;
	d.C::_a = 5;

在这里插入图片描述
在这里插入图片描述
菱形虚拟继承在内存中的分布情况:

	D d;
	d._b = 1;
	d._c = 2;
	d._d = 3;
	d.B::_a = 4;
	d.C::_a = 5;
	d._a = 6;

在这里插入图片描述
我们对最后的地址分析:(内存地址跟上图不一样是因为重新运行了一次)
在这里插入图片描述
这个虚基表是用来干什么的?
在这里插入图片描述
菱形虚拟继承的内存对象成员模型:这里可以分析出D对象中将A放到的了对象组成的最下面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A

下面是上面的Person关系菱形虚拟继承的原理解释:
在这里插入图片描述


如有错误或者不清楚的地方欢迎私信或者评论指出🚀🚀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/17690.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

凌恩生物美文分享|HGTree v2.0:水平基因转移数据库

水平基因转移(HGT)是指遗传物在物种间从一个相邻生物体到另一个生物体横向传递,是原核生物遗传变异的重要过程。HGT是负责塑造原核生物基因组和在自然选择中生存的驱动力之一,对原核生物的进化有很大贡献,但它会使物种进化史复杂化&#xff0…

【Linux】进程信号保存

前言 上篇博客我们了解了进程信号的概念和信号如何产生。 本篇我们将学习进程信号如何保存。 文章目录 前言一. 阻塞信号二. 递达动作三. 信号集四. 信号集操作函数结束语 一. 阻塞信号 首先我们需要一些预备知识 实际执行信号的处理动作称为信号递达(Delivery&am…

数字图像处理-绪论

数字图像处理-绪论 文章目录 前言一、闲谈二、什么是数字图像处理?2.1. 什么是数字图像?2.1.1. 可见光图像2.1.2. 不可见光图像 2.2. 什么是数字图像处理? 三、数字图像处理的前世今生3.1. 数字图像处理的前世3.2. 数字图像处理的今生 四、数…

【嵌入式系统】课程复习资料整理

【嵌入式系统】课程复习资料整理 一、绪论 1.定义 从技术的角度定义:以应用为中心、以计算机技术为基础、软件硬件可裁剪、对功能、可靠性、成本、体积、功耗严格要求的专用计算机系统。从系统的角度定义:嵌入式系统是设计完成复杂功能的硬件和软件&a…

使用crontab定时自动更新DDNS

需求说明: N1盒子的armbian系统配置好了 ipv6 的ddns,实现了域名访问本机,但是本地ipv6可能会发生变化,当发生变化后,需要手动执行指令,将新的ip与域名绑定,现在我们采用定时任务,每…

Nuvoton NK-980IOT开发板 u-boot 编译

前言 最近搭建了 Nuvoton NK-980IOT开发板 的开发编译环境,记录一下 u-boot 的 编译流程 Nuvoton NK-980IOT开发板 资源还是比较的丰富的,可以用于 嵌入式Linux 或者 RT-Thread 的学习开发 开发板上电比较的容易,两根 USB 线即可&#xff0…

计网笔记 01 概述 计算机网络体系结构、参考模型

文章目录 前言1、计网概述1.1 概念、组成、功能、分类1.1.1 概念1.1.2 计网组成1.1.2 计网分类 1.2 标准化工作及相关组织1.2.1 标准的分类 1.3 性能指标★★★1.3.1 速率相关性能指标1.3.2 时延相关指标 2、体系结构&参考模型★★★★★(对应王道视频7-10p 相当…

Android Jetpack:利用Palette进行图片取色

与产品MM那些事 新来一个产品MM,因为比较平,我们就叫她A妹吧。A妹来第一天就指出:页面顶部的Banner广告位的背景是白色的,太单调啦,人家不喜欢啦,需要根据广告图片的内容自动切换背景颜色,颜色…

基于CUDA的GPU计算PI值

访问【WRITE-BUG数字空间】_[内附完整源码和文档] 基于CUDA的GPU计算PI值。本项目使用CUDA编程模型并行计算PI值,研究GPU与CPU效率的比较,分析不同GPU线程分块对性能的影响。 异构计算试验报告 —实验1:基于CUDA的GPU计算PI值 第一部分&…

JS逆向 -- 某平台登录加密分析

一、打开网站,使用账号密码登录 账号:aiyou123.com 密码:123456 二、通过F12抓包,抓到如下数据,发现密码加密了 三、加密结果是32位,首先考虑是md5加密。 四、全局搜索pwd,点击右上角&#xf…

【ros2】ros melodic迁移到ros2 dashing过程中碰到的问题及解决方法

序言 总结踩坑经历,以利他人 1. error: forming pointer to reference type … & 报错原因: ros2回调函数的参数不能是引用形式 &,需要去除& 解决方法: 如果是指针引用,直接去除引用 void Callback(con…

javascript中的严格模式

认识严格模式: 在ECMAScript5标准中,JavaScript提出了严格模式的概念(Strict Mode): 严格模式很好理解,是一种具有限制性的JavaScript模式,从而是代码隐式的脱离了“懒散(sloppy)模…

软件测试实战,Web测试详细总结 (覆盖所有测试点),你要的都有

目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 Web自动化测试&…

在技术圈超卷的当下,学历到底是敲门砖还是枷锁?

前言 最近,突然之间被“孔乙己文学”刷屏了,短时间内“孔乙己文学”迅速走红,孔乙己是中国文学中的一位经典人物,他的长衫被认为是他的象征之一,孔乙己的长衫折射出很多现象,既有社会的,也有教育…

Android平台播放透明视频

Android平台播放透明视频 思路 设计一种特殊的视频,它的一半内容存储alpha信息,另一半内容存储rgb信息,接着通过OpenGL获取每个像素点的alpha值和rgb值进行混合,最后出来的画面就是带有透明效果的视频了。 可以上下的分&#xf…

服务器中了勒索病毒,升级后的Malox勒索病毒特征,勒索病毒解密数据恢复

Mallox勒索病毒是网络上较为流行的勒索病毒,但是随着黑客加密技术的不断升级,Mallox勒索病毒的新升级版本Malox勒索病毒已经开始出现。Malox勒索病毒是一种最近在网络上广泛传播的恶意软件,其感染方式多种多样,主要以加密受害人的…

基于zookeeper实现分布式锁

目录 zookeeper知识点复习 相关概念 java客户端操作 实现思路分析 基本实现 初始化链接 代码落地 优化:性能优化 实现阻塞锁 监听实现阻塞锁 优化:可重入锁 zk分布式锁小结 zookeeper知识点复习 Zookeeper(业界简称zk&#xff…

Zookeeper系统模型介绍

目录 一、数据模型 二、 节点的类型 (1)持久节点 (2)持久顺序节点 (3)临时节点 (4)临时顺序节点 三、客户端命令行 (1)创建节点 (2&…

最新VUE面试题

前言 本文以前端面试官的角度出发,对 Vue 框架中一些重要的特性、框架的原理以问题的形式进行整理汇总,意在帮助作者及读者自测下 Vue 掌握的程度。 本文章节结构以从易到难进行组织,建议读者按章节顺序进行阅读,当然大佬级别的…

操作系统——进程管理

0.关注博主有更多知识 操作系统入门知识合集 目录 0.关注博主有更多知识 4.1进程概念 4.1.1进程基本概念 思考题: 4.1.2进程状态 思考题: 4.1.3进程控制块PCB 4.2进程控制 思考题: 4.3线程 思考题: 4.4临界资源与临…