当前位置: 首页 > 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下执行创建语句&…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

python如何将word的doc另存为docx

将 DOCX 文件另存为 DOCX 格式&#xff08;Python 实现&#xff09; 在 Python 中&#xff0c;你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是&#xff0c;.doc 是旧的 Word 格式&#xff0c;而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...

Module Federation 和 Native Federation 的比较

前言 Module Federation 是 Webpack 5 引入的微前端架构方案&#xff0c;允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...

C++八股 —— 单例模式

文章目录 1. 基本概念2. 设计要点3. 实现方式4. 详解懒汉模式 1. 基本概念 线程安全&#xff08;Thread Safety&#xff09; 线程安全是指在多线程环境下&#xff0c;某个函数、类或代码片段能够被多个线程同时调用时&#xff0c;仍能保证数据的一致性和逻辑的正确性&#xf…...

C# 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

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

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

深度剖析 DeepSeek 开源模型部署与应用:策略、权衡与未来走向

在人工智能技术呈指数级发展的当下&#xff0c;大模型已然成为推动各行业变革的核心驱动力。DeepSeek 开源模型以其卓越的性能和灵活的开源特性&#xff0c;吸引了众多企业与开发者的目光。如何高效且合理地部署与运用 DeepSeek 模型&#xff0c;成为释放其巨大潜力的关键所在&…...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

【安全篇】金刚不坏之身:整合 Spring Security + JWT 实现无状态认证与授权

摘要 本文是《Spring Boot 实战派》系列的第四篇。我们将直面所有 Web 应用都无法回避的核心问题&#xff1a;安全。文章将详细阐述认证&#xff08;Authentication) 与授权&#xff08;Authorization的核心概念&#xff0c;对比传统 Session-Cookie 与现代 JWT&#xff08;JS…...

《信号与系统》第 6 章 信号与系统的时域和频域特性

目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...