C++继承(2)

news2024/12/29 9:51:36

目录

1.如何实现一个不可以被继承的类

2.继承和友元函数

3.继承和静态成员变量

4.菱形(虚拟)继承

(1)单继承和多继承

(2)菱形继承

(3)菱形继承的特殊情况

(4)虚继承机理分析

5.继承和组合

6.实战演练


1.如何实现一个不可以被继承的类

(1)我们上一次介绍了这个相关的构造函数和析构函数的派生类的诸多使用注意事项,我们如何实现一个不可以被继承的类呢,下面介绍两个方式;

(2)第一个就是使用的我们上次介绍的这个知识,我们可以把这个父类的构造函数定义为是私有的,这样的话,我们的这个类就是不可以被继承的,具体而言就会体现在这个我们在主函数里面使用这个类创建对象的时候就会报错;

(3)上面介绍的就是一种直接的方式,我们下面介绍一种间接的不可以被继承的方式,就是使用的C++11里面提供的一个关键字final,这个就很直接了,因为这个时候只要我们继承这个父类,这个时候编译器就会报错;

2.继承和友元函数

(1)这个地方只需要记住一句话,就是友元函数不可以被继承,如果子类里面也想要使用这个友元函数,我们就需要把这个函数定义为子类的友元,这个也是有办法解决的;

(2)友元函数不属于任何一个类,但是在友元函数里面,我们可以访问类里面的私有成员变量;如果我们不添加上子类里面的友元,这个时候我们的s是没有办法去访问受保护的成员变量的;在这个程序里面,我们可以把这个private理解成为和protected相同的意思;

(3)当我们在子类里面不添加友元函数的时候,我们没有办法去访问这个受保护的成员,这个地方也是可以证明我们的友元函数是不可以被继承的;

3.继承和静态成员变量

(1)静态成员变量在这个派生类里面是可以直接使用的,但是这两个是属于同一份的;

(2)实际上这个静态成员变量不属于对象,而是属于整个类域的,这个地方只是继承了它的使用权,静态成员变量和静态成员函数只要突破类域,我们就可以进行访问了;两个的地址是一样的,并不能说子类继承了父类的静态成员变量,但是这个子类也可以去使用静态成员变量;

(3)上面的这个案例就是使用静态的成员函数,以及这个继承的相关规则,去设计了一可以判断创建对象个数的程序,我们去创建父类对象的时候,静态成员变量就会count++,我们在创建子类对象的时候,同样去调用父类的构造函数,因为这个继承的时候,子类里面继承父类的成员变量需要使用父类的构造函数进行初始化;

4.菱形(虚拟)继承

(1)单继承和多继承

单继承就是只有一个直接父类的继承关系;

多继承就是一个类有两个及以上的直接父类的继承关系;

(2)菱形继承

菱形继承是有问题的,是属于这个多继承的一种特殊的情况,因为在这个下面的菱形继承里面,我们的assistant子类里面,有两份这个person的数据,一份是从student里面获得的,还有一份就是从teacher里面获得的;

这样的话就造成了数据的二义性,当我们进行访问的时候,编译器不知道我们想要访问那一份数据,这个就造成了数据的冗余和二义性,我们的解决办法就是使用虚拟继承,简称虚继承;

(3)菱形继承的特殊情况

上面的多继承需要在这个student类和teacher类里面使用virtual关键字,表示这个继承是一个虚拟继承,右边的这个需要把virtual添加在左边的中介,和右边的上面的那个类里面去;

右边的这个也是属于菱形继承的,只不过多了一层,我们可以把这个视为菱形继承,这个时候的virtual我们记住就是添加在和父类直接相连接的类上面,这样才可以解决二义性和数据冗余的问题;

(4)虚继承机理分析

我们是以下面的这个菱形继承作为案例进行分析的,这个D是子类,继承了BC类,A又被BC继承

实际上这个虚拟继承干的事情就是把这个A里面的数据单独的放到某一个位置里面去,我们想要访问这个数据的时候,是通过内存里面的一个偏移量的表去查看的,这个表里面表示出来了这个BC和A的偏移量的信息;我们可以通过这个偏移量找到这个相关的A里面的数据;

这个里面可能有些同学会说这个地方为什么不存储指针,通过指针我们也可以直接找到这个A里面的数据啊,为什么还要多此一举,搞出来一张偏移量表呢,实际上,这个表里面除了存储这个偏移量,还会存储一些其他的信息,这个信息如果全放在这个内存李敏就会很消耗空间吧;

总之,就是这个虚继承原理就是搞一张偏移量的表,我们通过这个表查找BC两个子类和A里面的数据的偏移量,而这个A里面的数据是被直接放在了其他的区域里面去的;

5.继承和组合

(1)继承我们上面已经介绍的很清楚了,组合就是在一个类里面去使用另外的一个类去定义对象,这个就是组合;

 

(2)上面的这段文字里面有这个黑箱和白箱,我们简单的说明一下,什么是黑箱,什么是白箱,黑箱就是指的这个里面的机理我们不是很清楚,我们只是凭借自己的认识和经验去揣测,白箱就是这个里面的机理我们是很清楚的,使用的什么语法,什么语句,我们是一清二楚的;

(3)具体到这个继承和组合上面而言,这个继承的类之间的关系就很清楚了,什么继承方式这个表示的就是很明显的,但是这个组合,我们在一个类里面去定义另外的一个类,但是至于两个类之间是什么关系,我们是很难去精确的描述的;

(4)继承的耦合度高,组合的耦合度低,这个耦合度指的就是不同的类,不同的模块之间的关联程度,我们从这个代码的实现上面去看,这个继承好像就会好一些,但是实际上,这个组合会更好,因为这个组合的模块之间的耦合度是很低的,就是说这个模块之间的关联性不是很强,我们对于某一个模块进行修改的时候,另外一个模块受到影响的可能性就会比较小;

(5)我们从软件工程的角度来讲,我们追求的是高内聚,低耦合,内聚就是这个每一个模块内部的这个代码,以及这个实现的过程是很健壮的,就是这个功能很全面,不会让两个模块之间的相似性很大,内聚就是做到泾渭分明,你实现你的功能,我实现我的功能,而且我们自己内部这个功能的实现是很成熟的,但是我们不会让这个耦合度很高;

但是这个并不意味着继承没有用,当这个程序里面的不同模块之间具有关联性的时候,这个继承还是有自己的用途的,只不过在这个两者皆可使用的情况下,我们会优先考虑使用组合的方式;

6.实战演练

(1)这个问题就是一个单继承问题

(2)我们画出来这个D对象的模型,这个里面包括他继承的东西,还有自己的东西;

我们的p1执行这个空间的开始位置,但是能够访问的范围只有base1这么大,p2就不会指向这个空间的开始位置,而是发生偏移,指向这个base2的起始位置,而且可以访问的空间只有base2的范围,但是这个p3指针指向的位置就是这个空间的起始位置,但是这个指针可以访问的范围就会比较大,这个模型他是都可以进行访问的,因为这个指针是一个derive类的;

(3)下面的这个是和虚继承相关的一道题目:

这个里面,我们的BC是共同使用同一份A的,我们这个打印的顺序是按照初始化列表的顺序,D里面的初始化列表里面先是B,但是这个B是A的继承,所以这个打印的结果就是ABCD,最后再去执行这个函数体,打印D;

这个里面A实际上就只会被初始化一次,因为这个A是BC公用的;

当我们把这个题目稍微变换一下,就是把这个虚函数的virtula去掉,这个A要调用几次初始化,这个时候只会进行两次初始化,这个时候的打印结果就是ABABC,因为这个时候已经不是虚继承了,而是普通的继承,B里面有一个A,C里面也有一个A,各自进行相应的初始化,这个时候D里面就不需要进行这个A的初始化了,这个时候A只会进行两次初始化的过程;这个地方不是虚继承,但是这个地方是满足菱形继承的,只不过我们没有使用虚继承的方式去解决这个问题而已;A的初始化要想执行三次,就必须要要3个A对象,但是这个菱形继承里面显然是没有3个A对象的,因此只会进行两次初始化;

我们把这个题目在虚继承的基础上面,把继承的顺序变换一下,就是原来的这个题目是先继承B,再去继承C,但是这个D里面的初始化列表的顺序是不变的,这个时候虽然在初始化列表里面显示B,后是C,但是这个打印的时候是按照声明的顺序打印的,这个里面集继承的顺序就是声明的顺序,即ACBD;

由此可见,这个继承里面的虚继承相对复杂,不建议我们日常去使用;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Unity2D - 状态机(State Machine)详解

1. 状态机概述 在角色的生成中,由于事件的不同,动作的不同,角色会处于不同的状态中。例如对战冒险游戏,面临Boss的攻击,角色会受到例如中毒,恐惧等Debuff效果,若单纯的在一个脚本中使用if等语句…

Linux Swap

Swap: 页面换出:就是在 Swap 机制下,当内存资源紧张时,内核就会把不经常使用的这些匿名页中的数据写入到 Swap 分区或者 Swap 文件中。从而释放这些数据所占用的内存空间。 页面换入:就是当进程再次访问那些被换出的数据时&…

中医对于帕金森病的病因和症状有何解释?

中医对帕金森病的病因解释 中医认为帕金森病的病因复杂多样,涉及多个方面。首先,精神因素如长期的情绪抑郁、悲伤、忧虑等精神不畅可能导致气机郁结,气血运行障碍,进而影响脑部神经系统的功能。其次,肝郁气滞也被认为…

怎么把amr格式转换为mp3格式?这6个mp3格式转换方法不容错过!

怎么把amr格式转换为mp3格式?AMR(自适应多速率)是一种音频编码格式,通常用于存储基于语音的文件,例如语音记录和VoIP应用,在3G移动设备上使用。它具有非常高的压缩比,导致声音质量较差。早期的安…

【Python机器学习】分类向量——数字可以编码分类变量

在adult数据集的例子中,分类变量被编码为字符。一方面可能会有拼写错误,但另一方面,它明确的将一个变量标记为分类变量。无论是为了便于存储还是因为数据的手机方式,分类变量通常被编码为整数。 假设adult数据集中的人口普查数据…

使用shell脚本编写监控系统资源(CPU,内存,磁盘)使用情况

🏡作者主页:点击! 🛠️Shell编程专栏:点击! ⏰️创作时间:2024年6月20日16点30分 🀄️文章质量:95分 目录 ————前言———— 1.本章目标 2.编写脚本 1.获取内…

Go 中使用map时注意的问题

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

uniapp uniCloud云开发

uniCloud概述 uniCloud 是 DCloud 联合阿里云、腾讯云、支付宝云,为开发者提供的基于 serverless 模式和 js 编程的云开发平台。 uniCloud 的 web控制台地址:https://unicloud.dcloud.net.cn 文档:https://doc.dcloud.net.cn/uniCloud/ un…

AI绘画:P图如此丝滑,OpenAI上线ChatGPT图像编辑功能,DallE-3绘画如此简单

大家好我是极客菌,用ChatGPT的DallE-3进行AI绘画对很多人来说是一个门槛很低的选择,现在OpenAI又重磅上线了图像编辑器功能(DallE editor),可以很方便的对图片的局部进行修改,而且支持中文,主打一个功能强大且好用&…

论文学习——一种自适应提升的动态多目标优化进化算法

论文题目:A dynamic multi-objective optimization evolutionary algorithm with adaptive boosting 一种自适应提升的动态多目标优化进化算法(Hu Peng a,b,∗, Jianpeng Xiong a, Chen Pi a, Xinyu Zhou c, Zhijian Wu d)IEEE Swarm and Ev…

FreeSWITCH 1.10.10 简单图形化界面24-呼入呼出编码

FreeSWITCH 1.10.10 简单图形化界面24-呼入呼出编码 FreeSWITCH GUI界面预览00、安装FreeSWITCH GUI先看使用手册1、语音接听还是视频接听2、排查 FreeSWITCH GUI界面预览 http://myfs.f3322.net:8020/ 用户名:admin,密码:admin FreeSWITCH…

MySQL之如何定位慢查询

1、如何定位慢查询 1.1、使用开源工具 调试工具:Arthas 运维工具:Promethuss、Skywalking 1.2、MySQL自带慢日志 慢查询日志记录了所有执行时间超过指定参数(long_query_time,单位:秒,默认10秒&#x…

The difference between Manhattan distance and Cosine Distance

题意:为什么即使返回了相同的文本块,曼哈顿距离(Manhattan Distance)和余弦距离(Cosine Distance)之间还是存在差异? 问题背景: I am using the qdrant DB and client for embeddin…

探索LangChain-Chatchat 0.3:一体化Agent与强大RAG模型的全面入门指南

介绍 LangChain-Chatchat 支持RAG和Agent0.3版本跟大模型解耦,支持Xinference、Ollama、LocalAI、FastChat、One API,可以非常方便的切换各个模型,本文只是介绍XinferenceXorbits Inference (Xinference) 是一个开源平台,用于简化各种 AI 模型的运行和集成。借助 X…

论文辅导 | 基于贝叶斯优化-卷积神经网络-双向长短期记忆神经网络的锂电池健康状态评估

辅导文章 模型描述 准确估计电池健康状态是设备稳定运行的关键。针对当前健康状态研究中容量难以直接测量、估计模型调参费时等问题,提出基于多健康特征的贝叶斯优化(BO)算法优化卷积神经网络(CNN)与双向长短期记忆&a…

气膜仓库的优势与应用—轻空间

随着现代物流和存储需求的不断增长,传统仓库的建设和运营成本日益增加,企业需要寻找更加灵活、高效和经济的解决方案。在这种背景下,气膜仓库作为一种新型仓储形式,以其独特的优势和广泛的应用前景,逐渐受到市场的青睐…

视频号视频怎么保存到手机,视频号视频怎么保存到手机相册里,苹果手机电脑都可以用

随着数字媒体的蓬勃发展,视频已成为我们日常生活中不可或缺的一部分。视频号作为众多视频分享平台中的一员,吸引了大量用户上传和分享各类精彩视频。然而,有时我们可能希望将视频号上的视频下载下来,以下将详细介绍如何将视频号的视频。 方法…

自养号测评助力:亚马逊、沃尔玛电商高效测评补单技巧,轻松实现销量与补单双赢

要在竞争激烈的市场中通过测评补单的方式提升产品权重和销售,构建一个稳定且高效的测评补单系统至关重要。通过精心培养一批高质量的买家账号,并深入了解真实买家的行为数据,结合对风控数据的精准把控,我们能够自主推动推广进程&a…

shell:处理命令行参数 获取用户输入

1. 命令行参数 1.1 位置参数 bash shell会将一些称为位置参数(positional parameter)的特殊变量分配给输入到命令行中的 所有参数。这也包括shell所执行的脚本名称。位置参数变量是标准的数字:$0是程序名,$1是第 一个参数,$2是第二个参数,依…

【LLM 评估】MMLU benchmark:用于衡量 LM 的多任务语言理解能力

论文:Measuring Massive Multitask Language Understanding ⭐⭐⭐⭐ ICLR 2021, arXiv:2009.03300 Code: GitHub 论文速读 本文提出了一个 benchmark:MMLU,一个覆盖了 57 个 subjects 的多项选择题的数据集。 数据集的 question 数量&…