【C++笔记】C++继承

【C++笔记】C++继承

  • 一、继承的概念
  • 二、继承的语法和权限
  • 三、父类和子类成员之间的关系
    • 3.1、子类赋值给父类(切片)
    • 3.2、同名成员
  • 四、子类中的默认成员函数
    • 4.1、构造函数
    • 4.2、拷贝构造
    • 4.3、析构函数
  • 五、C++继承大坑之“菱形继承”
    • 5.1、什么是“菱形继承”
    • 5.2、解决方法

一、继承的概念

继承:

继承是面向对象编程中的一个重要概念,它允许一个类(称为子类或派生类)继承另一个类(称为父类或基类)的属性和方法。继承是一种代码重用的方式,它可以减少代码的重复,提高代码的可维护性和可扩展性。
继承的基本原理是子类可以使用父类的属性和方法,而不需要重新编写代码。子类可以继承父类的公共属性和方法,也可以重写父类的方法或添加新的属性和方法。这种机制使得子类可以扩展父类的功能,同时保留父类的特性。

用一个简单的例子演示一下:
在这里插入图片描述
这里B继承了A,B不仅可以访问自己的成员变量,也可以访问自己父类的成员变量和成员函数。

二、继承的语法和权限

继承的语法格式如下:

class 子类名字:继承方式 父类名字{};

子类继承父类的继承方法有三种:

public
protected
private

(protected修饰的成员在内里边可以使用,在类外边不可以使用)
不同的修饰方法会使得子类中的父类成员权限不同,而且父类中以不同权限修饰符修饰的成员在继承到子类后的权限也会不同。
比如最简单的以public的方式继承:
在这里插入图片描述
public继承方式可以访问到父类中public的成员。
而如果是父类中的private成员就不行了:
在这里插入图片描述

还有其他的组合如下表:
在这里插入图片描述
有人可能会觉得这张表好复杂,觉得要背下来的话一定很困难。
其实我们并不需要去背这张表,我们仔细观察这张表之后就会发现其中的规律。
因为最后一个行都是不可见,我们可以把最后一行特殊化处理,然后剩下的我们仔细观察后就会发现,表中的任何一个结果都可以总结为:

min(父类中的修饰符,子类的继承方式)
在这里插入图片描述

三、父类和子类成员之间的关系

3.1、子类赋值给父类(切片)

因为子类继承了父类的成员,所以子类也可以看作是一种特殊的父类。那么将子类对象赋值给父类对象会怎么样呢?
在这里插入图片描述
我们发现父类自己的成员还是可以正常访问的,可若要是想访问子类的成员就不行了:
在这里插入图片描述
这样想跟我们平时理解的赋值不一样啊。

其实它在底层执行了一个“切片”操作:
在这里插入图片描述

因为父类中没有_id,所以父类并不会接收子类的_id,父类之后接受自己有的成员的值。
所以子类自己独有的成员也就被“切”掉了。

其他的赋值方式例如引用:
在这里插入图片描述
引用我们可以理解为,父类的引用只引用了子类中属于父类的那一部分。

指针:
在这里插入图片描述
指针其实是并不存在“切片”操作的,只需要执行子类的首地址即可,因为这是Person类型的指针,而指针能访问到的范围其实是由指针类型已经决定了的。
所以父类的指针只会访问到子类中属于父类的成员。

3.2、同名成员

同名成员变量:

有时候父类和之类中会存在一些同名成员变量,比如name:
在这里插入图片描述
这时候编译器会议子类的成员优先。
如果真要想访问到父类的就得要加上域作用限定符,限定为访问父类的:
在这里插入图片描述
同名成员函数:
如果父类和子类之中存在同名函数又会怎么样呢?
在这里插入图片描述
这其实就构成了“隐藏”,并不是函数重载,函数重载一定要是在同一作用域,而两个类之间并不是同一个作用域,即使他们之间是继承关系。
隐藏的条件是只需要函数名相同,对参数列表和返回值都没有要求。
这时候编译器还是会优先选择子类的函数,这也称之为父类的函数被子类的函数隐藏了。
这时候如果想要调用父类的,也需要加上域作用限定符:
在这里插入图片描述

四、子类中的默认成员函数

4.1、构造函数

我们来看看,继承关系中的构造函数会怎么做:
在这里插入图片描述

如果创建一个子类对象,编译器会先调父类的构造函数再调用子类的构造函数。

这其实是编译器自动调用的,即使我们没有显示的写出子类的构造函数,编译器也会自动去调用父类的构造函数:
在这里插入图片描述

而如果我们想要在子类中显示的构造父类对象,就必须将父类对象当成一个整体(当成一个对象)去构造,即调用父类的构造函数:
在这里插入图片描述
记住一定要在初始化列表处调用,不然就会存在父类构造被调用两次的问题:
在这里插入图片描述
这是因为编译器默认就会在初始化列表中调用父类构造函数。

而我们不能想当然的像下面这样初始化父类:
在这里插入图片描述
这是规定!

4.2、拷贝构造

拷贝构造也是要先调用父类的再调用子类的:
在这里插入图片描述
再构造函数中我们可以直接将子类对象传递给父类的构造函数,因为父类会通过“切片”操作拿到子类中父类的部分。

4.3、析构函数

析构函数和构造函数正好相反,析构要求的是先调用子类的析构再调用父类的析构。
在这里插入图片描述
而如果我们在子类的构造函数中显示的调用父类的构造函数就会发生调两次析构的危险:
在这里插入图片描述
而析构函数调用两次是很危险的,这很有可能就会导致同样的资源被释放两次的错误。

其实这是因为父类的析构函数是编译器自动调用且是在子类析构结束后才调用的,所以也就决定了它不能像构造函数一样写在初始化列表里。
也就不能自己调用,只能由编译器调用。

五、C++继承大坑之“菱形继承”

因为C++时出现的比较早的面向对象的语言,也就没有多少其他的面向对象语言可以参考,所以许多面向对象的“坑”也就避免不了了。
其中一个坑就是今天要讲的“菱形继承”。

5.1、什么是“菱形继承”

C++是支持多继承的,也就是一个类可能会存在多个直接父类,例如下面这个例子:
在这里插入图片描述
他们之间的继承关系如下图所示:
在这里插入图片描述
而如果这些关系再复杂一点儿,就会变成“菱形继承”了:
在这里插入图片描述
在这里插入图片描述
在这样的继承状态中,处于中间的A、B两个类是没有什么问题的,问题就出在最下面的C这个类:
在这里插入图片描述
从代码中我们并不能看出问题出在哪里,我们得到监视窗口中才能看出:
在这里插入图片描述
从内存中我们可以看到c1中竟然存了两个_o(一个是A继承的,一个是B继承的),这也就是为什么报错提示访问不明确的原因。

5.2、解决方法

方法一:加类域修饰
既然两个_o一个是A继承的,一个是B继承的,那我们直接指定是哪个类的不就行了:
在这里插入图片描述

方法二:virtual虚继承
还有一种方法就是在菱形继承的“腰部”加上virtual继承:
在这里插入图片描述
简单来说就是将菱形继承中具有公共父类和公共子类的那几个类继承其公共父类的方式全都改成虚继承。

虽然说菱形继承的问题已经被解决了,但是我们最好还是不要弄出菱形继承的好,多继承是没什么问题的,但是菱形继承就是个大坑。

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

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

相关文章

数据结构-- 并查集

0. 引入 并查集是来解决等价问题的数据结构。 离散数学中的二元关系。 等价关系需满足自反性、对称性、传递性。 a ∈ S , a R a a R b & b R a a R b ∩ b R c > a R c a \in S, aRa \\ aRb \& bRa \\ aRb \cap bRc >aRc a∈S,aRaaRb&bRaaRb∩bRc>a…

【Opencv】OpenCV使用CMake和MinGW的编译安装出错解决

编译时出现的错误: mingw32-make[1]: *** [modules/core/CMakeFiles/opencv_core.dir/all] Error 2 Makefile:161: recipe for target ‘all’ failed mingw32-make: *** [all] Error 2解决方法: 根据贴吧老哥的解答,发现是mingw版本有问题导…

【JAVA学习笔记】43 - 枚举类

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter11/src/com/yinhai/enum_ 〇、创建时自动填入版权 作者等信息 如何在每个文件创建的时候打入自己的信息以及版权呢 菜单栏-File-setting-Editor-File and Code Templaters -Includes-输入信…

自动化测试07Selenium01

目录 什么是自动化测试 Selenium介绍 Selenium是什么 Selenium特点 工作原理 SeleniumJava环境搭建 Selenium常用的API使用 定位元素findElement CSS选择语法 id选择器:#id 类选择 .class 标签选择器 标签名 后代选择器 父级选择器 自己选择器 xpath …

2.1 向量与线性方程组

一、行图像与列图像 线性代数的中心问题是求解线性方程组。线性的意思是这些方程的未知数是一次的,即每个未知数只会乘数字,而不会出现 x x x 与 y y y 相乘的项。下面是一个由两个未知数组成的方程组: 两个方程 两个未知数 { x − 2 y 1…

杂谈:DC对Verilog和SystemVerilog语言的支持

DC对Verilog和SystemVerilog语言的支持 设计语言用哪种?Design Compiler对二者的支持简单的fsm电路测试测试结果对比写在最后 设计语言用哪种? 直接抛出结论:先有电路,后为描述。设计端而言,没有语言的高低好坏&#…

妙手ERP功能更新丨Shopee全球产品支持使用定价模板修改价格、Ozon新增SKU模板 、Temu采集箱支持添加货源链接......

为了给卖家朋友带来更好的使用体验,更高效地运营跨境店铺,妙手ERP在近两周优化了以下多项功能。 01、平台授权模块 TikTok - 支持授权美国跨境店及ACCU店铺,TikTok平台各功能均可使用 02、产品模块优化 全平台 - 支持产品重量单位切换 Sho…

centos搭建elastic集群

1、环境可以在同一台集群上搭建elastic,也可以在三台机器上搭建,这次演示的是在同一台机器搭建机器。 2、下载elastic :https://www.elastic.co/cn/downloads/past-releases#elasticsearch 2、​​​​​​ tar -zxvf elasticsearch-xxx-版…

KNN(K近邻)水仙花的分类(含答案)

题目 以下采用K-NN算法来解决水仙花的分类问题,每个样本有两个特征,第一个为水仙花的花萼长度,第二个为水仙花 的花萼宽度,具体数据见表, 1)设置k3, 采用欧式距离,分析分类精度为多少…

vue如何使用冻结对象提升代码效率及其原理解析

先给大家伙整个实际工作中一定会碰到的问题 如下vue dome ,它的代码非常简单功能也1非常简单,就是一个按钮,点击后会显示有多少条数据 来看看源码, html部分就是一个按钮绑定了一个loadData事件,然后在p标签内展示了这个myData这个数据的长度 <template><div id&quo…

电解电容寿命与哪些因素有关?

电解电容在各类电源及电子产品中是不可替代的元器件&#xff0c;这些电子产品中由于应用环境的原因&#xff0c;使它成为最脆弱的一环&#xff0c;所以&#xff0c;电解电容的寿命也直接影响了电子产品的使用寿命。 一、电解电容失效模式与因素概述 铝电解电容器正极、负极引出…

proteus中仿真arduino的水位测试传感器

一、原理介绍 我们这里使用的水位传感器&#xff0c;只能说是一个小实验用途的水位传感器。我们首先上图 如上图所示&#xff0c;线没有连接&#xff0c;传感器由许5对裸露在外的铜线片作为传感部分&#xff0c;当浸入水中时这些铜线片会被水桥接。 这些被水连接起来的铜线&a…

最新Tuxera NTFS2023最新版Mac读写NTFS磁盘工具 更新详情介绍

Tuxera NTFS for Mac是一款Mac系统NTFS磁盘读写软件。在系统默认状态下&#xff0c;MacOSX只能实现对NTFS的读取功能&#xff0c;Tuxera NTFS可以帮助MacOS 系统的电脑顺利实现对NTFS分区的读/写功能。Tuxera NTFS 2023完美兼容最新版本的MacOS 11 Big Sur&#xff0c;在M1芯片…

Redis内存回收机制-内存淘汰策略和过期策略

Redis是基于内存操作的非关系型数据库&#xff0c;在内存空间不足的时候&#xff0c;为了保证程序的运行和命中率&#xff0c;就会淘汰一部分数据。如何淘汰数据&#xff1f;这就是Redis的内存回收策略。 Redis中的内存回收策略主要有两个方面&#xff1a; Redis过期策略&#…

UE4 UltraDynamicSky 天气与水体交互

最上面的Lerp的A通道为之前的水面效果&#xff0c;B是做的冰面效果 用Dynamic_Landscape_Weather_Effects的BaseColor的R通道四舍五入作为Lerp的Alpha值 使用一张贴图&#xff0c;乘以RadialGradientExponential对材质边缘做弱化&#xff0c;RadialGradientExponential的Raid…

【目标检测】Co-DETR:ATSS+Faster RCNN+DETR协作的先进检测器(ICCV 2023)

论文&#xff1a;DETRs with Collaborative Hybrid Assignments Training 代码**&#xff1a;https://github.com/Sense-X/Co-DETR 文章目录 摘要一、简介二、本文方法2.1.概述2.2.协同混合分配训练2.3. 定制的正 Query 生成2.4. Co-DETR为何有效1、丰富编码器的监督2、通过减少…

集成学习方法之随机森林-入门

1、 什么是集成学习方法 集成学习通过建立几个模型组合的来解决单一预测问题。它的工作原理是生成多个分类器/模型&#xff0c;各自独立地学习和作出预测。这些预测最后结合成组合预测&#xff0c;因此优于任何一个单分类的做出预测。 2、 什么是随机森林 在机器学习中&…

Axi接口的DDR3:参数,时序,握手机制

参考 AXI总线的Burst Type以及地址计算 | WRAP到底是怎么一回事&#xff1f;_axi wrap-CSDN博客 还有官方手册&#xff0c;名字太长想起来再写。 Transaction/Burst/Transfer/Beat Transaction指一次传输事务&#xff0c;实际上包括了address phase, data phase与response ph…

记录:Unity脚本的编写4.0

目录 前言导入音乐编写脚本 前言 之前使用脚本对uniry中的模型进行了控制&#xff0c;诸如使用键盘控制对象模型的移动或者使用鼠标对对象模型进行角度的切换&#xff08;或者是类似的东西&#xff09;&#xff0c;而我们在游戏的过程中&#xff0c;总是伴随着一些好听的bgm&a…

读书笔记之《敏捷测试从零开始》(一)

大家好&#xff0c;我是rainbowzhou。 子曰&#xff1a;学而时习之&#xff0c;不亦说乎&#xff1f;今天我想和大家分享一本测试书籍——《敏捷测试从零开始》。以下为我的读书笔记&#xff1a; 精彩片段摘录&#xff1a; 焦虑往往来自于对比&#xff0c;当你在自己的圈子里面…