当前位置: 首页 > news >正文

【C++进阶】继承

【C++进阶】继承

🥕个人主页:开敲🍉

🔥所属专栏:C++🥭

🌼文章目录🌼

1. 继承的概念及定义

    1.1 继承的概念

    1.2 继承定义

        1.2.1 定义格式

        1.2.2 继承父类成员访问方式的变化

    1.3 继承类模板

2. 父类和子类对象赋值兼容转换

3. 继承中的作用域

    3.1 隐藏规则:

4. 子类的默认成员函数

    4.1 4个常见默认成员函数

    4.2 实现一个无法被继承的类

5. 继承与友元

6. 继承与静态成员

7. 多继承及灵性继承问题

    7.1 继承模型

    7.2 虚继承

    7.3 多继承中的指针偏移问题

8. 继承和组合

    8.1 继承和组合

1. 继承的概念及定义
    1.1 继承的概念

  继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许我们在保持原有类特性的基础上进行扩展,增加方法(成员函数)和属性(成员变量),这样产生新的类,称子类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的函数层次的复用,继承是类设计层次的复用。

  下⾯我们看到没有继承之前我们设计了两个类Student和Teacher,Student和Teacher都有姓名/地址/电话/年龄等成员变量,都有identity⾝份认证的成员函数,设计到两个类里面就是冗余的。当然他们也有⼀些不同的成员变量和函数,比如老师独有成员变量是职称,学⽣的独有成员变量是学号;学⽣的独有成员函数是学习,老师的独有成员函数是授课

class Teacher
{
public:
    void identity()
    {
        //身份认证
    }
private:
    size_t _age;//年龄
    string _name;//姓名
    string _address;//地址
    string _tel;//电话

    string _title;//学号
};


class Student
{
private:
    size_t _age;//年龄
    string _name;//姓名
    string _address;//地址
    string _tel;//电话

    string _stuid;//职称
};

    下面我们公共的成员都放到Person类中,Student和teacher都继承Person,就可以复用这些成员,就不需要重复定义了,省去了很多麻烦。

class Person
{
public:
public:
    void identity()
    {
        //身份认证
    }

    size_t _age;//年龄
    string _name;//姓名
    string _address;//地址
    string _tel;//电话
};


class Teacher:public Person
{
private:
    string _title;//学号
};


class Student:public Person
{
private:
    string _stuid;//职称
};

    1.2 继承定义
        1.2.1 定义格式

  从上面我们看到,Person是父类,也可以称为基类,Student和Teacher是子类,也可以称为派生类。继承方式如下图:

  可以看到,这里的继承方式所用的关键字和我们访问限定符的关键字是一样的:

        1.2.2 继承父类成员访问方式的变化

  

总结如下:

  子类中的父类成员的访问方式取决于 父类对这些成员的访问限定符与继承方式 中权限较小的。

  比如,父类的成员用private限定,继承方式用public,那么实际上父类中的成员继承到子类中后,也是private,因此子类虽然继承了父类的成员,但是不可访问。

    1.3 继承类模板

  这里我们实现一个栈的类,继承的是库中的vector,因此我们在实现栈的功能:尾插、尾删、获取栈顶元素等操作时,就可以调用vector中的函数。

2. 父类和子类对象赋值兼容转换

  public继承的子类对象可以赋值给父类的对象/父类的指针/父类的引用。这里有个形象的说法叫切片或者切割。寓意把子类中父类那部分切来赋值过去。

  父类对象不能赋值给子类对象。

3. 继承中的作用域
    3.1 隐藏规则:

在继承体系中父类和子类都有独立的作用域。

子类和父类中有同名成员,子类中将会屏蔽对父类中的同名成员的直接访问,这种情况叫隐藏。如果想要访问父类中的同名成员,使用 父类 :: 同名成员  即可访问。

子类和父类中的成员函数只要函数名相同就构成隐藏,不受其他因素限制。

因此在继承体系中不建议定义同名函数。

4. 子类的默认成员函数
    4.1 4个常见默认成员函数

  默认成员函数是指我们不写,编译器会帮我们自动生成,常见的4个默认成员函数有:构造函数、析构函数、拷贝构造函数、operator=。那么在子类中,这4个默认成员函数是如何生成的呢?

  子类的构造函数必须调用父类的构造函数初始化父类的那⼀部分成员。如果父类没有默认的构造函数,则必须在子类构造函数的初始化列表阶段显示调用。

 ② 子类的析构函数会在被调用完成后自动调用父类的析构函数清理父类成员。因为这样才能保证子类对象先清理子类成员再清理父类成员的顺序。

  子类对象初始化时先调用父类对象的构造函数再调用子类对象的构造函数。

  ④ 子类的拷贝构造函数必须调用父类的拷贝构造完成父类的拷贝初始化。

   子类的operator=必须要调用父类的operator=完成父类的复制。需要注意的是子类的operator=隐藏了父类的operator=,所以显示调用父类的operator=,需要指定父类作用域。

    4.2 实现一个无法被继承的类

方法1:将父类的构造函数设为private,因为在构造子类对象时必须要调用父类对象的构造函数,而父类对象的构造函数设为私有无法访问,因此也就无法被继承。

方法2:使用final修饰父类,就不能够被继承了。finale有最后的意思,这里可以理解为最终类。

5. 继承与友元

  友元关系不能继承,也就是说父类友元不能访问子类私有和保护成员

6. 继承与静态成员

  父类定义了static静态成员,则整个继承体系里面只有⼀个这样的成员。无论派生出多少个子类,都只有⼀个static成员实例。

7. 多继承及灵性继承问题
    7.1 继承模型

  单继承:一个子类只有一个父类的情况我们称为单继承。

  多继承:一个子类有两个或者两个以上的父类时称为多继承,多继承对象在内存中存储的方式为:先继承的父类在最前面,后面继承的父类按照顺序排列,子类的成员排在最后。

  菱形继承:菱形继承是多继承的一种特殊情况。

  从上面可以看出,fun2和fun3都继承了fun1,都存有了一份size_t _fun1,而fun0继承了fun2和fun3,因此不可避免地fun0中存有了两份fun1中的size_t _fun1,这就会导致数据冗余和⼆义性。支持多继承就一定会存在菱形继承的问题,实践中使用多继承是务必要小心谨慎。

  这里在访问_fun1时系统报错说fun0::_fun1不明确,也就是这里的两份_fun1,系统也不知道你要访问的是哪一份。这就是二义性问题。

    7.2 虚继承

  那我们在实践中不可避免地要写出菱形继承,但是又想避免数据冗余和⼆义性的问题该如何做呢?这里就需要使用到virtual关键字:

    7.3 多继承中的指针偏移问题

来看一道例题:

关于多继承中指针偏移问题,下面选项正确的是()  

    A. f1==f2==f3      B. f1<f2<f3      C. f1==f3!=f2      D. f1!=f2!=f3

代码:

class fun1
{
public:
    size_t _fun1;
};

class fun2
{
public:
    size_t _fun2;
};


class fun3 :public fun1, public fun2
{
private:
    size_t _fun3;
};


int main()
{
    fun3 f3;

    fun1* f1 = &f3;
    fun2* f2 = &f3;


    return 0;
}

  正确答案:C

  为什么呢?一张图弄明白:

8. 继承和组合
    8.1 继承和组合

继承是一种is-a的关系。意思就是每个子类对象都是一个父类对象,就好比是有血缘关系的父子,儿子有自己不同于父亲之处,同时也一定有与父亲的相同之处,相同之处便是子类继承父类的那一部分。

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

组合是一种has-a的关系。可以理解为数学中的集合,{1,2,3}和{1,2,3,4,5,6}的关系,前者是后者的子集后者包含前者。

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

 优先使用组合,而不是继承。实际尽量多去用组合,组合的耦合度低,代码维护性好。不过也不太那么绝对,类之间的关系就适合继承(is-a)那就用继承,另外要实现多态,也必须要继承。类之间的关系既适合用继承(is-a)也适合组合(has-a),那就用组合。

 很多人说C++语法复杂,其实多继承就是⼀个体现。有了多继承,就存在菱形继承,有了菱形继承就有菱形虚拟继承,底层实现就很复杂,并不像我们想的那么简单,性能也会有⼀些损失,所以最好不要设计出菱形继承。多继承可以认为是C++的缺陷之一,后来的⼀些编程语⾔都没有多继承,如Java。

                                                 创作不易,点个赞呗,蟹蟹啦~

相关文章:

【C++进阶】继承

【C进阶】继承 &#x1f955;个人主页&#xff1a;开敲&#x1f349; &#x1f525;所属专栏&#xff1a;C&#x1f96d; &#x1f33c;文章目录&#x1f33c; 1. 继承的概念及定义 1.1 继承的概念 1.2 继承定义 1.2.1 定义格式 1.2.2 继承父类成员访问方式的变化 1.3 继承类模…...

立体相机镜面重建(一)镜面标定

无论是单目、双目或者是多屏幕镜面重建&#xff0c;都需要事先对屏幕和相机的相对位置进行标定&#xff0c;求得相机到屏幕之间的相对变换关系。如果求得屏幕和相机之间的变换关系呢&#xff1f;接下来是标定流程。 &#xff08;一&#xff09;准备&#xff1a; 1&#xff09…...

【如何有效解决前端Vue中的常见难题】

&#x1f41f;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢编程&#x1fab4; &#x1f419;个人主页&#x1f947;&#xff1a;Aic山鱼&#x1f420;WeChat&#xff1a;z7010cyy &#x1f988;系列专栏&#xff1a;&#x1f3de;️ 前端-JS基础专栏✨前端-Vue框架专栏…...

CLAMP-1靶机渗透测试

一、靶机下载地址 https://www.vulnhub.com/entry/clamp-101,320/ 二、信息收集 1、主机发现 # 使用命令 nmap 192.168.145.0/24 -sn | grep -B 2 "00:0C:29:88:B4:BF" 2、端口扫描 # 使用命令 nmap 192.168.145.0/24 -p- -sV 3、指纹识别 # 使用命令 whatweb …...

JavaScript中的Truthy Falsy值以及等号判断

1.Falsy & Truthy Falsy的值false&#xff0c;0&#xff0c;-0&#xff0c; “”&#xff0c; null&#xff0c; undefined&#xff0c;NaNTruthy的值除了以上之外的其他值 2.等号判断 console.log(10 10); console.log(0 ); console.log(0 false); console.log( fa…...

uniapp——展开和收起

案例展示 代码 后台返回的数据格式如下&#xff1a; {1: "大富科技速度快放假手动阀",2: "第三方斯蒂芬斯蒂芬是的开发时间",4: "45345345",5: "电饭锅电饭锅地方" }<view class"tipTitle">温馨提示</view> &l…...

WebGL2学习(2): GLSL ES 3.0

更多精彩内容尽在 dt.sim3d.cn &#xff0c;关注公众号【sky的数孪技术】&#xff0c;技术交流、源码下载请添加VX&#xff1a;digital_twin123 WebGL 2.0 给 GLSL 带来了重大变化。WebGL 1.0 中使用的 GLSL 版本是 GLSL ES 1.0。 WebGL 2.0 中仍然可用。但是&#xff0c;通过编…...

[大模型实战] DAMODEL云算力平台部署LLama3.1大语言模型

[大模型实战] DAMODEL云算力平台部署LLama3.1大语言模型 目录 一、LLama3.1二、DAMODEL云算力平台2.1 提供的服务2.1.1 AI训练2.1.2 AI推理2.1.3 高性能计算2.1.4 图像&#xff0f;视频渲染2.1.5 定制化部署 2.2 支持的GPU 三、在DAMODEL部署LLama3.13.1 在DAMODEL创建实例&…...

驱动开发系列09 - Linux设备模型之设备,驱动和总线

一:概述 Linux 设备模型(LDM)是 Linux 内核中引入的一个概念。用于管理内核对象(那些需要引用计数的对象、例如文件、设备、总线甚至驱动程序),以及描述它们之间的层次结构,以及这些内核对象之间绑定关系。Linux 设备模型引入了对象生命周期管理、引用计数、以及面向对象…...

HTML实现弹出层

leopard/ˈlepərd/ 豹子&#xff0c;豹纹 弹出层指的是鼠标悬停于某个元素之上时显示的一个界面组件。 关注和理解特性&#xff1a;z-index属性和动态生成HTML元素。 HTML5新增&#xff1a; figure:媒体内容(图像&#xff0c;音频&#xff0c;视频)&#xff0c;用于包含一…...

Android控件详解

在Android应用程序中&#xff0c;界面由布局和组件组成。布局相当于框架&#xff0c;而控件则是框架里面的内容。了解过Android布局后&#xff0c;如果要设计ui界面&#xff0c;还需要了解和掌握各个控件的应用。 一个界面的设计&#xff0c;先从创建容器开始&#xff0c;再向…...

记忆化搜索专题篇

目录 斐波那契数 不同路径 最长递增子序列 猜数字大小II 矩阵中的最长递增路径 声明&#xff1a;下面将主要使用递归记忆化搜索来解决问题&#xff01;&#xff01;&#xff01; 斐波那契数 题目 思路 斐波那契数的特点就是除了第一个数是0&#xff0c;第二个数是1&…...

入网测评检查项大全(安全资料)

1. Linux操作系统 2. Windows操作系统 3. Tomcat中间件 4. Nginx中间件 5. Mysql数据库 6. Weblogic中间件 7. Oracle数据库 8. Redis数据库 9. 达梦数据库 10. 应用系统 11. 渗透测试 13 .AIX操作系统 14 .中创中间件 15 .IIS中间件 16 .Apache中间件 17 .Mari…...

uni-app 开发App时调用uni-push 实现在线系统消息推送通知 保姆教程

一、引言 在开发App时避免不了需要推送系统通知&#xff0c;以提高用户的使用体验。在自己的一个工具型的小app上全流程接入了uni-push2.0的推送能力&#xff0c;做个记录&#xff0c;以防后期需要用到。在阅读本教程前最好先看看官方文档&#xff0c;结合官方文档使用&#xf…...

13.StringRedisTemplete使用

上一篇说到改变了RedisTemplate的默认序列化器后&#xff0c;在redis中存入Java对象后&#xff0c;在redis中的呈现是&#xff1a;会记录类的字节码 这也是代码中可以强制装换为对应的java对象的原因&#xff1a; Test void testStudent() {redisTemplate.opsForValue().set(&q…...

[工具]-gitee+pycharm-配置

安装git ​ 查看git是否安装设置成功&#xff1a; ​ git config user.name ​ git config user.email ​ 码云账号设置邮箱 pycharm设置gitee 打开 PyCharm&#xff0c;在 Settings - Plugins 里面&#xff0c;搜索 Gitee 插件&#xff0c;安装后重启 PyCharm。 pychar…...

中间件是一种在客户端和服务器之间进行通信和处理的软件组件或服务

中间件是一种在客户端和服务器之间进行通信和处理的软件组件或服务。中间件位于应用程序和操作系统之间&#xff0c;可以提供一些功能&#xff0c;如请求转发、数据转换、安全性和身份验证、日志记录等。 中间件的主要作用是将应用程序与底层基础设施解耦&#xff0c;提供了一…...

RCE-eval长度限制突破技巧

目录 一、长度17的限制绕过 1、最简单的绕过 &#xff08;一&#xff09;绕过 &#xff08;二&#xff09;编写一句话木马 2、文件包含的利用 &#xff08;一&#xff09;远程文件包含的利用 &#xff08;二&#xff09;本地文件包含的利用 3、usort绕过 &#xff08…...

【黑马】MyBatis

目录 MyBatis简介JDBC缺点&#xff1a;MyBatis针对于JDBC进行简化&#xff0c;简化思路&#xff1a; MyBatis快速入门具体构建步骤解决SQL映射文件的警告提示 Mapper代理开发案例&#xff1a;使用Mapper代理方式完成案例具体步骤详解&#xff1a;Mapper代理方式 Mapper核心配置…...

oracle创建dblink使得数据库A能够访问数据库B表LMEAS_MFG_FM的数据

1、给数据库A普通用户CMRONLINE相应的权限&#xff0c;在sys用户下执行以下语句 GRANT CREATE DATABASE LINK TO CMRONLINE; GRANT DROP PUBLIC DATABASE LINK TO CMRONLINE; GRANT CREATE PUBLIC DATABASE LINK TO CMRONLINE; 2、在数据库A用户 CMRONLINE下执行创建语句&…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

HBuilderX安装(uni-app和小程序开发)

下载HBuilderX 访问官方网站&#xff1a;https://www.dcloud.io/hbuilderx.html 根据您的操作系统选择合适版本&#xff1a; Windows版&#xff08;推荐下载标准版&#xff09; Windows系统安装步骤 运行安装程序&#xff1a; 双击下载的.exe安装文件 如果出现安全提示&…...

【AI学习】三、AI算法中的向量

在人工智能&#xff08;AI&#xff09;算法中&#xff0c;向量&#xff08;Vector&#xff09;是一种将现实世界中的数据&#xff08;如图像、文本、音频等&#xff09;转化为计算机可处理的数值型特征表示的工具。它是连接人类认知&#xff08;如语义、视觉特征&#xff09;与…...

WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成

厌倦手动写WordPress文章&#xff1f;AI自动生成&#xff0c;效率提升10倍&#xff01; 支持多语言、自动配图、定时发布&#xff0c;让内容创作更轻松&#xff01; AI内容生成 → 不想每天写文章&#xff1f;AI一键生成高质量内容&#xff01;多语言支持 → 跨境电商必备&am…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

基于IDIG-GAN的小样本电机轴承故障诊断

目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) ​梯度归一化(Gradient Normalization)​​ (2) ​判别器梯度间隙正则化(Discriminator Gradient Gap Regularization)​​ (3) ​自注意力机制(Self-Attention)​​ 3. 完整损失函数 二…...

智能职业发展系统:AI驱动的职业规划平台技术解析

智能职业发展系统&#xff1a;AI驱动的职业规划平台技术解析 引言&#xff1a;数字时代的职业革命 在当今瞬息万变的就业市场中&#xff0c;传统的职业规划方法已无法满足个人和企业的需求。据统计&#xff0c;全球每年有超过2亿人面临职业转型困境&#xff0c;而企业也因此遭…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...

Redis上篇--知识点总结

Redis上篇–解析 本文大部分知识整理自网上&#xff0c;在正文结束后都会附上参考地址。如果想要深入或者详细学习可以通过文末链接跳转学习。 1. 基本介绍 Redis 是一个开源的、高性能的 内存键值数据库&#xff0c;Redis 的键值对中的 key 就是字符串对象&#xff0c;而 val…...