【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继承:
在这里插入图片描述
简单来说就是将菱形继承中具有公共父类和公共子类的那几个类继承其公共父类的方式全都改成虚继承。

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

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

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

相关文章

数据交换技术

一、数据交换 数据交换是实现在大规模网络核心上进行数据传输的技术基础。 常见的数据交换技术包括 电路交换报文交换分组交换 基于不同交换技术构建的网络分别称之为电路交换网络、报文交换网络和分组交换网络。 发展演变图: a) 电路交换 电路交换是最早出现…

JEnv使用初体验

Java多版本控制器初体验 1、前言 由于公司项目使用jdk8版本,而日常学习会使用其他版本例如jdk17等,往常都是修改环境配置目录实现。 2、下载资料 链接:https://pan.baidu.com/s/1UqzHv8K8WBu-75Ysyc_h3A 提取码:ra6a 3、安装 …

TYWZOJ 种树苗 待定题解

文章目录 题目描述输入格式输出格式样例样例输入样例输出 数据范围与提示思路与部分实现完整代码 题目描述 在游戏 Minecraft 中,玩家可以通过种树来使木材再生。玩家需要将树苗种在泥土上,然后等待它长成大树,期间可以利用骨粉来催熟树苗。…

Linux——文件权限属性和权限管理

文件权限属性和权限管理 本章思维导图: 注:本章思维导图对应的Xmid文件和.png文件都以传到“资源” 文章目录 文件权限属性和权限管理1. sudo提权和sudoers文件1.1 sudo提权和成为root的区别 2. 权限2.1 Linux群体2.1.1 为什么要有所属组2.1.2 修改文件…

汇编运算符和表达式

运算符: 汇编语言由表达式和运算符组成,运算符分为数值运算符和属性运算符。属性运算符面向变量或标号。 数值运算符: 算术运算符: 运算符类型 ✓ ( 正号 ) 、 -( 负号 ) ✓ ( 加 ) 、 -( 减 ) 、 *( 乘 ) 、 /( 除 ) 、 MO…

centos中安装Mysql8.0

其实和mysql5.7的安装差不多 1.root用户 2.更新密钥 rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2022 3.安装mysql yum库 rpm -Uvh https://dev.mysql.com/ get/mysql80-community-release-el7-2.noarch.rpm 4.通过上两步,我们就可以使用yum去安装…

2023-10-21 美团2024秋招后端开发岗笔试题

1 考察dfs和拓扑排序 1.1 题目描述(如果拓扑排序不清楚可以去做一下lc 207. 课程表) 1.2 答案 import java.util.*;public class Meituan {static int m,n;public static void main(String[] args) {Scanner in new Scanner(System.in);m in.nextInt…

Controller接收Postman的raw参数时,属性值全部为空

Controller接收Postman的raw参数时,属性值全部为空 情景再现 在进行业务代码的编写过程中,使用Postman等工具调用Controller接口时,发现属性值全部为空后端代码如下: Requset对象为: public class QuerySkuRequest …

Openssl数据安全传输平台017:客户端在Linux上的编译与调试

客户端代码在widows上编译,除了protobuf找不到目录,其他的基本没有什么问题。 然后打开虚拟机,项目文件已经在/home/projects目录下了 进入项目文件,对代码进行编译 第一次 // 找不到protobuf g *.cpp *.cc -ljson -lpthread -…

雨云OSS服务介绍和使用教程,以及Chevereto图床使用雨云OSS的教程

雨云OSS(对象存储)服务介绍和使用教程,以及Chevereto图床程序使用雨云OSS的教程 雨云OSS(对象存储)是一种基于S3协议的云端数据存储服务,它可以帮助你将数据安全、高效地存储在云端,并且可以随…

队列(Queue)概念+通过单、双链表来模拟队列+环形队列+OJ面试题(用队列实现栈、用栈实现队列、设计环形队列)

文章目录 队列(Queue)一、 概念1.尾进头出 二、模拟队列1.单链表实现队列1.1 设置结点1.2 入队offer1.3出队 poll1.4 empty方法,peek方法,getUsedSize方法 2.双链表实现队列2.1 创建结点2.2 入队列2.3 出队列2.4 peek、size、isEmpty方法 三、环形队列1.…

一键添加命名前缀(文件)

(一)需求描述 在上班摸鱼的我正准备打开手机刷会儿CSDN论坛,老板发给我一个压缩包并要求我给里面所有的文件的名称添加一个前缀”大项目_”。我本以为只有几个文件需要改,便没放在心上,反倒是心里暗暗吐槽老板“这么简…

c++设计模式二:原型模式

使用场景:当需要构建多个相同的类对象时,而且该类对象结构较为复杂,如果每个都重新组织构建会很麻烦。 其实,就是写一个拷贝构造函数,或者写一个拷贝每个成员变量的clone()方法。 举例说明:比如一个相亲网站…

Megatron-LM GPT 源码分析(四) Virtual Pipeline Parallel分析

引言 本文接着上一篇【Megatron-LM GPT 源码分析(三) Pipeline Parallel分析】,基于开源代码 GitHub - NVIDIA/Megatron-LM: Ongoing research training transformer models at scale ,通过GPT的模型运行示例,从三个维…

51单片机复位电容计算与分析(附带Proteus电路图)

因为iC x (dU/dt).在上电瞬间,U从0变化到U,所以这一瞬间就是通的,然后这就是一个直流回路,因为电容C直流中是断路的,所以就不通了。 然后来分析一下这个电容的电压到底是能不能达到单片机需要的复位电压。 这是一个线性电容&…

Django 全局配置 settings 详解

文章目录 1 概述1.1 Django 目录结构 2 常用配置:settings.py2.1 注册 APP:INSTALLED_APPS2.2 模板路径:TEMPLATES2.3 静态文件:STATICFILES_DIRS2.4 数据库:DATABASES2.5 允许访问的主机:ALLOWED_HOSTS 1 …

算法通过村第十七关-贪心|黄金笔记|跳跃游戏

文章目录 前言跳跃游戏最短跳跃游戏总结 前言 提示:曾走过山,走过水,其实只是借助他们走过我的生命;我看着天,看着地,其实只是借助它们确定我的位置;我爱这她,爱着你,其实…

RabbitMQ (4)

RabbitMQ (4) 文章目录 1. 死信的概念2. 死信的来源3. 死信代码案例3.1 TTL 过期时间3.2 超过队列最大长度3.3 拒绝消息 前言   上文我们已经学习完 交换机 ,知道了几个交换机的使用 ,下面我们来学习一下 死信队列 1. 死信的概念 先从概念解释上搞清楚这…

BUUCTF刷题记录

[BJDCTF2020]Easy MD51 进入题目页面,题目提示有一个链接,应该是题目源码 进入环境,是一个查询框,无论输入什么都没有回显,查看源码也没什么用 利用bp抓包查看有没有什么有用的东西 发现响应的Hint那里有一个sql语句&…

WIN11新版画图问题解决

1 白色背景被连同删除的问题 解决方法:加层 将层调整为新建的层,在这个层下画图就行。 2 QQ截图无法直接放在画图上的问题 使用QQ截图的时候: 解决方法:使用windows自带的截图工具 步骤: 1. 使用快捷键winshifts 2.…