【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…

关于QTableWidget的it所占内存的释放问题

说起QTableWidget,我们一般都是用QTableWidget进行数据显示或者使用QTableWidget其他控件组合进行设置。 这里主要说说数据展示,我们在进行数据展示时,数据量分为两种有限和无限。不管是QTableWidget中插入的数据有限还是数据无限。在数据多时…

【从0到1设计一个网关】什么是网关?以及为什么需要自研网关?

文章目录 什么是网关?网关类型网关的优缺点目前的网关解决方案有哪些?为什么要自研Gateway网关?自研网关需要注意什么? 注: 这篇文章作为我的网关的第一篇文章,并不涉及任何代码,只是提及了网关…

LeetCode 155. 掷骰子等于目标和的方法数:动态规划

【LetMeFly】1155.掷骰子等于目标和的方法数:动态规划 力扣题目链接:https://leetcode.cn/problems/number-of-dice-rolls-with-target-sum/ 这里有 n 个一样的骰子,每个骰子上都有 k 个面,分别标号为 1 到 k 。 给定三个整数 …

如何在国际腾讯云服务器上设置IP节点的密码?

跟着云计算技术的发展,越来越多的企业和个人开始运用云服务器来存储和处理数据。腾讯云服务器是一款非常受欢迎的云服务器产品,它提供了高效稳定的计算能力。在运用腾讯云服务器的过程中,咱们可能需求设置IP节点的暗码,以便维护咱…

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

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

Gin vs Beego: Golang的Web框架之争

前言 Golang作为一门高效且简洁的语言,已经在Web开发领域得到了广泛的应用。Gin和Beego是Golang中两个著名的Web框架,它们都提供了一系列强大的功能,帮助开发者构建高性能的Web应用。本文将对Gin和Beego进行全面的对比,帮助开发者…

SQL SERVER连接oracle数据库几种方法

--1 方式 --查询oracle数据库中的表 SELECT * FROM OPENDATASOURCE( MSDAORA, Data SourceGE160;User IDDAIMIN;PasswordDAIMIN )..DAIMIN.JOBS 举一反三:在查询分析器中输入: SELECT * FROM OPENDATASOURCE( MSDAORA, Data SourceORCL;User…

vite.config.js文件配置代理设置VITE_APP_BASE_API

.env.development文件 ENV development # base api VITE_APP_BASE_API /dev-api.env.production文件 ENV production # base api VITE_APP_BASE_API /apidefine: {process.env: {VITE_APP_BASE_API: https://xxx.com}},server: {hmr: true, // vue3 vite配置热更新不用手动…

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

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

Java架构师内功数据库

目录 1 导学2 数据库基本概念2.1 数据库系统2.2 三级模式-两级映像2.3 数据库设计2.4 数据模型2.4.1 E-R模型2.4.2 关系模型2.5 关系代数3 规范化和并发控制3.1 函数依赖3.2 键与约束3.3 范式3.3.1 第一范式1NF3.3.2 第二范式3.3.3 第三范式3.4 模式分解3.5 并发控制3.6 封锁协…

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…

详解如何快速查询Node.js版本信息(六种方法)

Node.js是一款基于Chrome V8引擎的快速、轻量级的JavaScript运行时。随着应用程序规模越来越庞大&#xff0c;Node.js版本的更新也日益频繁。这篇文章旨在帮助开发者们快速查询Node.js版本信息。 一、使用node命令查询版本信息 node命令提供了一个参数-v&#xff0c;可以在控…

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

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