【C++】继承(下)

大家好,我是苏貝,本篇博客带大家了解C++的继承(下),如果你觉得我写的还不错的话,可以给我一个赞👍吗,感谢❤️
在这里插入图片描述


目录

  • 5.继承与友元
  • 6.继承与静态成员
  • 7.复杂的菱形继承及菱形虚拟继承
  • 8.继承的总结和反思
  • 9.笔试面试题

5.继承与友元

友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员,就像父母的朋友不是你的朋友一样
在这里插入图片描述

6.继承与静态成员

基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。父类静态成员属于当前类,也属于当前类的所有派生类,因此无论派生出多少个子类,都只有一个static成员实例

在这里插入图片描述
在这里插入图片描述

如果我们想知道A及其派生类实例化了多少对象,就可以定义一个static变量

在这里插入图片描述

在这里插入图片描述

7.复杂的菱形继承及菱形虚拟继承

单继承:一个子类只有一个直接父类时称这个继承关系为单继承

在这里插入图片描述

多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承
在这里插入图片描述

多继承的定义如上图的Assistant,只需要在原本继承的基础上加逗号和其它基类即可

菱形继承:菱形继承是多继承的一种特殊情况。比如助教,对老师来说,他是个学生;对学生来说,他是个老师。因此他有学生和老师两个身份,就继承了学生类和老师类
在这里插入图片描述

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性(后面介绍)的问题。
在这里插入图片描述

数据冗余:在Assistant的对象中Person成员会有两份。
二义性:Student和Teacher类都有_name,无法明确知道访问的是哪一个

在这里插入图片描述
在这里插入图片描述

虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和 Teacher的继承Person时使用虚拟继承(在继承公共的基类时用虚拟继承),即只保存1份Person的成员,就不会造成数据冗余,二义性也就解决了。需要注意的是,虚拟继承不要在其他地方去使用。

在这里插入图片描述
在这里插入图片描述

在上面这种菱形继承中,虚拟继承用在菱形的腰部B和C,那下图的用在哪呢?也是B和C,virtual放在有公共基类(A)的类中
在这里插入图片描述

虚拟继承解决数据冗余和二义性的原理:
为了研究虚拟继承原理,我们给出了一个简化的菱形继承继承体系,再借助内存窗口观察对象成员的模型。

下面是不加虚拟继承的菱形继承
在这里插入图片描述

在这里插入图片描述

我们可以从内存窗口看出,D里面包含2份A的成员,会导致数据冗余和二义性。因为类D先继承B,再继承C,因此D类的对象d中,先出现类B的成员,再是类C的成员,最后是类D的成员。
同理,如果类D先继承C,再继承B,那么D类的对象d中,先出现类C的成员,再是类B的成员,最后是类D的成员。

下面我们加上虚拟继承
在这里插入图片描述
在这里插入图片描述

我们可以从内存窗口看出,D里面只包含1份A的成员,不会导致数据冗余和二义性。而且这时的B和C类的成员中都不包含本来有的A类成员,并且都存储了一个地址(0x00677bdc和0x00677be4,机器是小端存储),我们来看看这2个地址指向的内容

在这里插入图片描述
在这里插入图片描述

原来地址指向的空间(叫虚基表)里存放的是与A的成员的偏移量(还有其它的内容,这里不做介绍)

为什么要存偏移量?在切片的时候有用。将d赋值给类B的对象bb,就要把D类中B类那部分切来赋值过去,可是这里的B类的成员不包括A类的成员,因此B类保存的地址就能找到与A类的成员的偏移量,就能找到A类的成员,才能最终将B类的成员赋值给bb

在这里插入图片描述

多继承本身没有问题,但有多继承就可能导致菱形继承

总结:实践中可以设计多继承,但切记不要设计菱形继承,因为太复杂,容易出现各种问题

问:下面哪个选项是正确的?
在这里插入图片描述

A:p1 == p2 == p3
B:p1 < p2 < p3
C:p1 == p3 != p2
D:p1 != p2 != p3

答案:C
在这里插入图片描述

问:下面哪个选项是正确的?
在这里插入图片描述

A:p1 == p2 == p3
B:p1 < p2 < p3
C:p2 == p3 != p1
D:p1 != p2 != p3

答案:C
在这里插入图片描述

问:下面程序的结果是什么?
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

类D的对象定义时先走初始化列表,再走函数体,所以”class D”一定在最后。先声明的先走初始化列表,D类中先声明的是B类,B继承A,所以A比B更先声明,再声明C,最后D。因此A->B->C->D

8.继承的总结和反思

1、 很多人说C++语法复杂,其实多继承就是一个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂。所以一般不建议设计出多继承,一定不要设计出菱形继承。否则在复杂度及性能上都有问题。
2、 多继承可以认为是C++的缺陷之一,很多后来的语言都没有多继承,如Java。
3、 继承和组合
组合是什么?将一个类(如A)作为成员变量放在另一个类中(如B)
在这里插入图片描述

public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。

适合is-a的关系,如人和学生,就用is-a。适合has-a的关系,如汽车和轮胎,就用has-a。is-a和has-a都可以,如链表和栈,就用has-a。即优先使用对象组合,而非类继承

继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称为白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,基类的内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。

对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复用(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被封装。

实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用继承,可以用组合,就用组合。

9.笔试面试题

1、 什么是菱形继承?菱形继承的问题是什么?
2、 什么是菱形虚拟继承?如何解决数据冗余和二义性的
3、 继承和组合的区别?什么时候用继承?什么时候用组合?

复用的常见体现:
1、 函数逻辑的复用
2、 模板
3、 继承
4、 组合


好了,那么本篇博客就到此结束了,如果你觉得本篇博客对你有些帮助,可以给个大大的赞👍吗,感谢看到这里,我们下篇博客见❤️

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

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

相关文章

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(九)(完结篇)

文章目录 一、成绩查询模块实现1、学生成绩查询功能实现1.1 页面设计1.2 前端页面实现1.3 后端功能实现2、成绩分段查询功能实现2.1 页面设计2.2 前端页面实现2.3 后端功能实现二、试卷练习模块实现三、我的分数模块实现1、 页面设计2、 前端页面实现3、 后端功能实现四、交流区…

【流媒体】搭建流媒体服务器

搭建Windows Nginx服务器 搭建 下载nginx工具包解压至本地&#xff0c;并在cmd窗口中切换至nginx所在的本地目录修改 conf/nginx.conf 文件&#xff0c;更改其端口号 server中的 listen的端口号从 80改为 8080&#xff0c;因为80经常被其他服务占用&#xff0c;导致无法打开 …

携程Java开发面试题及参考答案 (200道-下)

insert 一行数据的时候加的是什么锁?为什么? 在 MySQL 中,当执行 INSERT 操作插入一行数据时,加锁的情况会因存储引擎和具体的事务隔离级别而有所不同。一般来说,在 InnoDB 存储引擎下,INSERT 操作加的是行级排他锁(Row Exclusive Lock),以下详细说明原因。 行级排他…

洛谷P11655「FAOI-R5」Lovely 139

P11655「FAOI-R5」Lovely 139 题目背景 Update&#xff1a;数据有 0 0&#xff0c;答案为 1&#xff0c;请选手特判以正常通过。 Height ≤ 139 \text{Height}\leq139 Height≤139。 题目描述 对于一个 01 \tt 01 01 串 S S S&#xff08;下标从 1 1 1 开始&#xff09;…

【Linux】24.进程信号(1)

文章目录 1. 信号入门1.1 进程与信号的相关知识1.2 技术应用角度的信号1.3 注意1.4 信号概念1.5 信号处理常见方式概览 2. 产生信号2.1 通过终端按键产生信号2.2 调用系统函数向进程发信号2.3 由软件条件产生信号2.4 硬件异常产生信号2.5 信号保存 3. 阻塞信号3.1 信号其他相关…

《手札·开源篇》从开源到商业化:中小企业的低成本数字化转型路径 ——以Odoo为数据中台低成本实现售前售中一体化

某机电设备有限公司数字化转型案例&#xff1a;以Odoo为数据中台实现售前售中一体化 一、企业背景某机电设备有限公司在机电设备领域历经多年发展&#xff0c;业务广泛&#xff0c;涵盖工业自动化设备、电力设备等产品的销售与服务。随着业务版图不断拓展&#xff0c;企业面临…

笔试-业务逻辑4

应用 小明在玩一个数字加减游戏&#xff0c;输入4个正整数&#xff1a;s、t、a、b&#xff0c;其中s>1&#xff0c;b<105&#xff0c;a!b。只使用加法或者减法&#xff0c;使得st。 每回合&#xff0c;小明用当前的数字&#xff0c;加上或减去一个数字&#xff1b;目前有…

Windows 中的 WSL:开启你的 Linux 之旅

今天在安装windows上安装Docker Desktop的时候&#xff0c;遇到了WSL。下面咱们就学习下。 欢迎来到涛涛聊AI 一、什么是 WSL&#xff1f; WSL&#xff0c;全称为 Windows Subsystem for Linux&#xff0c;是微软为 Windows 系统开发的一个兼容层&#xff0c;它允许用户在 Win…

编程题-电话号码的字母组合(中等)

题目&#xff1a; 给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 解法一&#xff08;哈希表动态添加&#xff09;&#x…

python:如何播放 .spx 声音文件

.spx 是 Speex音频编解码器的文件扩展名&#xff0c;它是一种开源的、免费的音频编解码器&#xff0c;主要用于语音压缩和语音通信领域。spx 文件通常用于语音记录、VoIP应用、语音信箱等场景。 .mp3 是一种广泛使用的音频格式&#xff0c;它采用了有损压缩算法&#xff0c;可…

数据结构课程设计(三)构建决策树

3 决策树 3.1 需求规格说明 【问题描述】 ID3算法是一种贪心算法&#xff0c;用来构造决策树。ID3算法起源于概念学习系统&#xff08;CLS&#xff09;&#xff0c;以信息熵的下降速度为选取测试属性的标准&#xff0c;即在每个节点选取还尚未被用来划分的具有最高信息增益的…

Vue3学习笔记-事件-4

一、事件处理 使用v-on或者后面加事件&#xff1a; <template><button v-on:click"addCount()">{{count}}</button> </template> 二、事件传参 传event&#xff1a; 不传参时&#xff0c;默认自动接收 event 传自定义参数时&#xff0c…

Node.js下载安装及环境配置

目录 一、下载 1. 查看电脑版本&#xff0c;下载对应的安装包 2. 下载路径下载 | Node.js 中文网 二、安装步骤 1. 双击安装包 2. 点击Next下一步 3. 选择安装路径 4. 这里我选择默认配置&#xff0c;继续Next下一步&#xff08;大家按需选择&#xff09; 5. 最后inst…

k8s二进制集群之ETCD集群证书生成

安装cfssl工具配置CA证书请求文件创建CA证书创建CA证书策略配置etcd证书请求文件生成etcd证书 继续上一篇文章《负载均衡器高可用部署》下面介绍一下etcd证书生成配置。其中涉及到的ip地址和证书基本信息请替换成你自己的信息。 安装cfssl工具 下载cfssl安装包 https://github…

使用python实现与本地ollama部署的deepseek对话

专栏总目录 按照ollama官方doc的example操作&#xff0c;没有成功与本地ollama上的deepseek-r1:1.5b通讯后&#xff0c;发现vscode可以调用本地ollama上的deepseek模型。 为了实现与ollama上的deepseek模型通讯&#xff0c;我使用wireshark对本地回环地址进行侦听后&#xff0c…

【大模型理论篇】最近大火的DeepSeek-R1初探系列1

1. 背景介绍 这一整个春节&#xff0c;被DeepSeek-R1刷屏。各种铺天盖地的新闻以及老板发的相关信息&#xff0c;着实感受到DeepSeek-R1在国外出圈的震撼。 DeepSeek推出了新的推理模型&#xff1a;DeepSeek-R1-Zero 和 DeepSeek-R1。DeepSeek-R1-Zero 是一个在没有经过监督微调…

C++哈希表深度解析:从原理到实现,全面掌握高效键值对存储

目录 一、核心组件与原理 1. 哈希函数&#xff08;Hash Function&#xff09; 2. 冲突解决&#xff08;Collision Resolution&#xff09; 3. 负载因子&#xff08;Load Factor&#xff09;与扩容 二、C实现&#xff1a;std::unordered_map 1. 模板参数 2. 关键操作与复…

Pandoc, Zotero, JabRef 管理论文引用,生成参考文献 | 撰写论文 paper

书接上回&#xff0c;使用 Obsidian, Zotero, JabRef, Pandoc, Markup-Markdown | 撰写论文 paper 管理论文引用&#xff0c;生成参考文献 TL; DR导出 bibliography 文件JabRefZotero 参考文献引用语法reference-docLinks TL; DR 安装 pandoc v3.6.2. 使用一下命令&#xff0c…

为AI聊天工具添加一个知识系统 之85 详细设计之26 批流一体式 与数据提取器

Q843、批流一体式 统一数据处理框架 "批流一体式统一数据处理框架" 这一概念通常指的是一种将批处理&#xff08;Batch Processing&#xff09;和流处理&#xff08;Stream Processing&#xff09;结合在一起的数据处理架构。它的目标是提供一个统一的框架&#xff…

深入理解 `box-sizing: border-box;`:CSS 布局的利器

深入理解 box-sizing: border-box;&#xff1a;CSS 布局的利器 默认行为示例代码 使用 box-sizing: border-box;示例代码 全局应用 box-sizing: border-box;示例代码 实际应用场景1. 表单布局2. 网格布局 总结 在 CSS 中&#xff0c;box-sizing 属性决定了元素的总宽度和高度是…