C++进阶:继承
文章目录
- 继承的概念
- 继承的定义方式
- 继承关系和访问限定符
- 基类和派生类对象的赋值转换
- 继承中的作用域
- 派生类中的默认成员函数
- 构造函数
- 拷贝构造函数
- 赋值拷贝函数
- 析构函数
- 总结
继承的概念
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保
持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象
程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继
承是类设计层次的复用。
继承中的一些概念:
基类:被一个类继承的类叫做基类。
派生类:继承另一个类的类叫做派生类。
继承的使用场景,当我们有很多个类时,很多个类都有一些共同的特性,有共同的成员变量或者成员函数时,我们就可以把这些特性封装成一个公共的基类,再通过这些类继承这个公共的基类,如果个别类有独特的特性的话,可以单独写在成员变量或者成员函数当中。
继承的定义方式
class A
{
private:public:int _a;
};
class B :public A
{
public:private:int _b;
};
上面的代码是B类继承A类,A类作为基类,B类作为派生类
继承关系和访问限定符
继承方式有三种,public继承,private继承,protected继承,继承方式可以显示写,也可以不写,如果不写的话,class的默认继承方式是private,struct默认继承方式是public。
访问限定符有三种:public,private,protected
这里有一个规则 : 基类的私有成员在子类都是不可见。基类的其他成员在子类的访问方式 = Min(成员在基类的访问限定符,继承方式)public > protected>private。大概规则就是在继承方式和访问限定符中取最小的一个,如果访问限定符是public,但是继承方式是private,那么最后就取private,就不能访问基类成员,只要有private就不能访问基类的成员。
注意:这里这是不能访问,但是还是继承了
可以看到这里是继承了,但是不能访问
如果对访问方式还是不清楚的,可以看看上面的表格,再看看上面的规则。
总结:
- 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私
有成员还是被继承到了派生类对象中,但是语法上限制派生类对象不管在类里面还是类外面
都不能去访问它。 - 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在
派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。 - 实际上面的表格我们进行一下总结会发现,基类的私有成员在子类都是不可见。基类的其他
成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式)public > protected> private。 - 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过
最好显示的写出继承方式。 - 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡
使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里
面使用,实际中扩展维护性不强
基类和派生类对象的赋值转换
class A
{
private:public:int _a;
};
class B :public A
{
public:B(){}
private:int _b;
};
对于上面这个类来说,我们做以下事情。
int main()
{B b;A a;a = b;A& ref = b;A* Ptr = &b;return 0;
}
这是不是类型转换呢?很显然a和b不是一个类型,如果我们只看赋值操作的话,可能还会认为可能是类型转换,但是如果我们看看下面的引用ref等于b的话就会打消这个念头了,我们知道类型转换会产生临时变量,临时变量具有常性,所以这里引用不能引用一个具有常性的变量,所以这里应该加const,但是实践过程当中这里并没有报错,所以这里肯定不是类型转换,这里是一个特殊规则:赋值兼容转换。
什么事赋值兼容转换呢?
派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片
或者切割。寓意把派生类中父类那部分切来赋值过去。
我们可以这样理解:
赋值兼容转换可以理解为,我们将一个派生类拷贝给一个基类实际上是把派生类中的基类部分拿出来单独给基类,这里就像切片一样,把派生类切开,把基类的部分给基类,所以这里才取名为切片或者切割。
int main()
{B b;A a;a = b;A& ref = b;A* Ptr = &b;return 0;
}
这里如果我们 改变ref对应的成员变量相应的b中的对应的继承下来的成员变量也会变,指针也相同,这里我们讨论的是public情况下,如果是private就不能进行赋值兼容转换。
继承中的作用域
首先我们讨论一下,基类和派生类中是否可以存在相同的函数或者变量,答案是肯定的,首先作用域不同,可以存在相同的函数或者变量。
class A
{
public:void fun(){cout << "func()" << endl;}
};
class B : public A
{
public:void fun(int i){A::fun();cout << "func(int i)->" <<i<<endl;}
};
对于上面这两个类来说,下面这个函数调用的是哪个fun呢?
void Test()B b;b.fun(10);
};
这里很显然调用的是B中的fun(),因为有参数,但是下面这个呢?
void Test()B b;b.fun();
};
上面这个调用的哪个fun呢?这里就不卖关子了,这里会报错。
这里直接会报编译错误,如果我们想调用A类中的函数怎么办呢?
我们可以像下面一样调用。
void Test()
{B b;b.A::fun();
};
像上面这样调用就可以直接调用A类中的相同函数。
这里我们提一下,这两个同名函数的关系,这两个同名函数构成隐藏。
派生类中的默认成员函数
构造函数
由于我们是先继承的基类的成员,所以我们实例化的时候,也是先定义的基类的成员,所以在初始化的时候我们也是先初始化基类的成员变量
可以看到这里先初始化的是基类的成员,即便我将基类的构造函数写在初始化列表的后面,根据这个也可以断定基类的成员变量是在派生类原本的成员变量之前定义的,因为初始化列表的初始化顺序是和声明的顺序一致的,这说明在派生类中继承的基类的成员是先声明的,这也说明应该先初始化基类成员再初始化派生类成员。
拷贝构造函数
class A
{
public:A(int a = 0):_a(a){}A(const A& a):_a(a._a){}
private:int _a;
};
class B : public A
{
public:B(int a = 0, int b = 0):_b(b),A(a){}B(const B& b):_b(b._b),A(b){}
private:int _b;
};
对于拷贝构造来说这里就要用到刚刚我们刚刚讲到的切片,也就是赋值兼容转换,如果是派生类的成员变量的话,就直接走初始化列表直接进行初始化,但是对于基类的成员这里我们直接调用基类的默认的拷贝构造函数,这里我们直接传的变量是类型为B的,这里会做一个切片,直接将属于传递过去用的是A类接收,所以这里会做一个切片,传递过去只接受了A类的部分。
赋值拷贝函数
//A类的赋值拷贝函数A& operator=(const A& a){_a = a._a;}//B类的赋值拷贝函数B& operator=(const B& b){_b = b._b;A::operator=(b);}
需要注意的是,我们在复用基类的赋值拷贝函数的时候,需要说明一下作用域,因为两个赋值拷贝函数构成隐藏,所以调用的时候会优先调用派生类的赋值拷贝函数,所以这里如果不指定作用域的话,会出现无穷递归,很明显下面就出现了无穷递归,所以这里要指定作用域。
析构函数
对于析构函数来说,首先我们要知道的是,在我们调用构造函数的时候,先初始化的是基类的成员,所以应该是基类成员先初始化,然后再初始化派生类自身的成员,所以这里应该是基类的成员先入栈,派生类再入栈,所以这里我们应该先保证先析构派生类的成员变量,再析构基类的成员变量,我们需要保证这一点,由于C++的机制,C++在析构完派生类的成员变量的时候,会直接自动调用基类的析构函数,所以我们并不用显示调用析构函数,但是如果我们也可以显示调用。
这里是因为多态的某些原因,后面细讲。
这里应该指定作用域,所以应该像下面一样调用。
但是我们可以看见,一个对象调用了两次析构,而且还是先析构的是基类成员,所以这里我们就不需要显示写出来,直接等编译器自动调用即可。
总结
继承是面向对象编程中的一个核心概念,通过它我们能够实现代码的重用和扩展。在本篇博客中,我们从继承的基本概念开始,逐步深入探讨了继承的定义方式、继承关系中的访问限定符以及基类和派生类对象之间的赋值转换。我们还讨论了继承中的作用域问题以及派生类中的默认成员函数,包括构造函数、拷贝构造函数、赋值拷贝函数和析构函数。
特别地,我们重点分析了析构函数在多态性中的作用。通过将基类的析构函数声明为虚函数,确保在基类指针指向派生类对象时,能够正确调用派生类的析构函数,从而避免资源泄露和内存管理问题。
通过这些内容的学习,我们不仅理解了继承的基本原理和实现方法,还掌握了如何在实际编程中应用这些知识,提高代码的可维护性和扩展性。希望这些内容能为大家提供有价值的参考,帮助大家更好地理解和应用继承这一重要的编程概念。
相关文章:
C++进阶:继承
文章目录 继承的概念继承的定义方式继承关系和访问限定符基类和派生类对象的赋值转换继承中的作用域派生类中的默认成员函数构造函数拷贝构造函数赋值拷贝函数析构函数 总结 继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允…...
SFTP工具
SFTP工具 工具类配置类调用 工具类 Slf4j Component public class SFTPUtils {Resourceprivate SftpConfig sftpConfig;Session session null;Channel channel null;/*** 网络图片url** param fileUrl* throws JSchException*/public String uploadFileSFTP(String fileUrl) …...
服务器数据恢复—vxfs文件系统元数据被破坏的数据恢复案例
服务器存储数据恢复环境: 某品牌MSA2000服务器存储中有一组由8块SAS硬盘组建的raid5磁盘阵列,其中包含一块热备盘。分配了6个LUN,均分配给HP-Unix小机使用。磁盘分区由LVM进行管理,存放的数据主要为Oracle数据库及OA服务端。 服务…...
【SCAU数据挖掘】数据挖掘期末总复习题库简答题及解析——上
1.K-Means 假定我们对A、B、C、D四个样品分别测量两个变量,得到的结果见下表。 样品 变量 X1X2 A 5 3 B -1 1 C 1 -2 D -3 -2 利用K-Means方法将以上的样品聚成两类。为了实施均值法(K-Means)聚类,首先将这些样品随意分成两类(A、B)和(C、…...
云时代的Java:在云环境中实施Java的最佳实践
引言 云计算已经成为现代软件开发不可或缺的一部分,它提供了灵活性、可扩展性和成本效益。对于Java开发者来说,掌握在云环境中部署和管理Java应用的最佳实践是至关重要的。本文将探讨一些关键策略,帮助你最大化Java在云平台上的性能和效率。…...
STL - 常用算法
概述: 算法主要是由头文件<algorithm><functional><numeric>组成<algorithm>是所有STL头文件中最大的一个,范围涉及比较、 交换、查找、遍历操作、复制、修改等等<numeric>体积很小,只包括几个在序列上面进行…...
Qt | QTextStream 类(文本流)
01、字符编码 1、怎样将字符转换为二进制形式进行存储,存在一个编码的问题,通常都需进行两次编码, 2、字符集:字符的第一次编码是将字符编码为与一个数值(如一个 10 进制整数)相对应,比如把字符 A 编码为 10 进制的 65,B 编码为 66 等。把每一个字符都编码为与一个数值…...
Python学习笔记7:入门知识(七)
前言 之前说过我更换了新的学习路线,现在是根据官方文档和书籍Python crash course来进行学习的,在目前的学习中,对于之前的知识有一些遗漏,这里进行补充。 学习资料有两个,书籍中文版PDF,关注我私信发送…...
如何翻译和本地化游戏?翻译访谈
如何翻译和本地化游戏?这个过程的技术细节有哪些?游戏翻译不同于电影翻译。Logrus IT游戏本地化部门负责人阿列克谢费奥多罗夫(Alexey Fedorov)在接受RUDN语言学系外语系教授和研究人员的采访时谈到了这一点,他是由尤利…...
[C++] 从零实现一个ping服务
💻文章目录 前言ICMP概念报文格式 Ping服务实现系统调用函数具体实现运行测试 总结 前言 ping命令,因为其简单、易用等特点,几乎所有的操作系统都内置了一个ping命令。如果你是一名C初学者,对网络编程、系统编程有所了解ÿ…...
2024网络安全学习路线 非常详细 推荐学习
关键词:网络安全入门、渗透测试学习、零基础学安全、网络安全学习路线 首先咱们聊聊,学习网络安全方向通常会有哪些问题 1、打基础时间太长 学基础花费很长时间,光语言都有几门,有些人会倒在学习 linux 系统及命令的路上&#…...
STM32F103ZET6_HAL_CAN
1定义时钟 2定义按键 按键上拉电阻 3开启串口 4打开CAN(具体什么意思上一篇讲了) 5生成代码 /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief …...
javaWeb项目-ssm+vue网上租车系统功能介绍
本项目源码:java-基于ssmvue的网上租车系统源码说明文档资料资源-CSDN文库 项目关键技术 开发工具:IDEA 、Eclipse 编程语言: Java 数据库: MySQL5.7 框架:ssm、Springboot 前端:Vue、ElementUI 关键技术:springboot、…...
Go模板页面浏览器显示HTML源码问题
<!--* Title: This is a file for ……* Author: JackieZheng* Date: 2024-06-09 17:00:01* LastEditTime: 2024-06-09 17:01:12* LastEditors: Please set LastEditors* Description:* FilePath: \\GoCode\\templates\\index.html --> <!DOCTYPE html> <html …...
弃用Docker Desktop:在WSL2中玩转Docker之Docker Engine 部署与WSL入门
Docker技术概论 在WSL2中玩转Docker之Docker Engine部署 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite:http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://bl…...
Mac下载了docker,在终端使用docker命令时用不了
问题:在mac使用docker的时候,拉取docker镜像失败 原因:docker是需要用app使用的 ,所以在使用的时候必须打开这个桌面端软件才可以在终端上使用docker命令!!!...
Spring Security——基于MyBatis
目录 项目总结 新建一个项目 pom.xml application.properties配置文件 User实体类 UserMapper映射接口 UserService访问数据库中的用户信息 WebSecurityConfig配置类 MyAuthenticationFailureHandler登录失败后 MyAuthenticationSuccessHandlerw登录成功后 WebSecur…...
Qt——升级系列(Level Four):控件概述、QWidget 核心属性、按钮类控件
目录 控件概述 QWidget 核心属性 核心属性概览 enabled geometry windowTitle windowIcon windowOpacity cursor font toolTip focusPolicy styleSheet 按钮类控件 Push Button Radio Buttion Check Box Tool Button 控件概述 Widget 是 Qt 中的核⼼概念. 英⽂原义是 "…...
品质卓越为你打造App UI 风格
品质卓越为你打造App UI 风格...
ei期刊和sci期刊的区别
ei期刊和sci期刊的区别 ei期刊和sci期刊的区别是什么?Sci和ei都属于国际期刊的一种,但是二者之间存在一些区别,选择期刊投稿时需要注意这些区别。EI期刊刊物的审查周期短,SCI学术期刊的审查期长。难度要求不同,SCI期刊比EI期刊对…...
从零手写实现 nginx-20-placeholder 占位符 $
前言 大家好,我是老马。很高兴遇到你。 我们为 java 开发者实现了 java 版本的 nginx https://github.com/houbb/nginx4j 如果你想知道 servlet 如何处理的,可以参考我的另一个项目: 手写从零实现简易版 tomcat minicat 手写 nginx 系列 …...
leetcode290:单词规律
题目链接:290. 单词规律 - 力扣(LeetCode) class Solution { public:bool wordPattern(string pattern, string s) {unordered_map<char, string> s2t;unordered_map<string, char> t2s;int len pattern.size();int CountSpace…...
IDEA 2022
介绍 【尚硅谷IDEA安装idea实战教程(百万播放,新版来袭)】 jetbrains 中文官网 IDEA 官网 IDEA 从 IDEA 2022.1 版本开始支持 JDK 17,也就是说如果想要使用 JDK 17,那么就要下载 IDEA 2022.1 或之后的版本。 公司…...
Vue TypeScript 实战:掌握静态类型编程
title: Vue TypeScript 实战:掌握静态类型编程 date: 2024/6/10 updated: 2024/6/10 excerpt: 这篇文章介绍了如何在TypeScript环境下为Vue.js应用搭建项目结构,包括初始化配置、创建Vue组件、实现状态管理利用Vuex、配置路由以及性能优化的方法&#x…...
Hudi extraMetadata 研究总结
前言 研究总结 Hudi extraMetadata ,记录研究过程。主要目的是通过 extraMetadata 保存 source 表的 commitTime (checkpoint), 来实现增量读Hudi表写Hudi表时,保存增量读状态的事务性,实现类似于流任务中的 exactly-once 背景需求 有个需求:增量读Hudi表关联其他Hudi…...
Vue31-自定义指令:总结
一、自定义函数的陷阱 1-1、自定义函数名 自定义函数名,不能用驼峰式!!! 示例1: 示例2: 1-2、指令回调函数的this 【回顾】: 所有由vue管理的函数,里面的this直接就是vm实例对象。…...
Windows环境如何使用Flutter Version Manager (fvm)
Windows环境如何使用Flutter Version Manager (fvm) Flutter Version Manager (fvm) 是一个用于管理多个 Flutter SDK 版本的命令行工具,它允许开发者在不同项目之间轻松切换 Flutter 版本。这对于需要维护多个使用不同 Flutter 版本的项目的开发人员来说非常有用。…...
优化Elasticsearch搜索性能:查询调优与索引设计
在构建基于 Elasticsearch 的搜索解决方案时,性能优化是关键。本文将深入探讨如何通过查询调优和索引设计来优化 Elasticsearch 的搜索性能,从而提高用户体验和系统效率。 查询调优 优化查询是提高 Elasticsearch 性能的重要方法。以下是一些有效的查询…...
STM32-17-DAC
STM32-01-认识单片机 STM32-02-基础知识 STM32-03-HAL库 STM32-04-时钟树 STM32-05-SYSTEM文件夹 STM32-06-GPIO STM32-07-外部中断 STM32-08-串口 STM32-09-IWDG和WWDG STM32-10-定时器 STM32-11-电容触摸按键 STM32-12-OLED模块 STM32-13-MPU STM32-14-FSMC_LCD STM32-15-DMA…...
一杯咖啡的艺术 | 如何利用数字孪生技术做出完美的意式浓缩咖啡?
若您对数据分析以及人工智能感兴趣,欢迎与我们一起站在全球视野关注人工智能的发展,与Forrester 、德勤、麦肯锡等全球知名企业共探AI如何加速制造进程, 共同参与6月20日由Altair主办的面向工程师的全球线上人工智能会议“AI for Engineers”…...
郑州制作网站设计/多用户建站平台
从事.NET开发快2年了,意识到了到了自身发展受限制,也意识到了系统的学习计算机科学理论功底的重要性了。当初自己算是“无师自通”,成为了一个不知名的“代码工人”。如今在应用层Web开发“混”了2年,还算勉强吧。论天赋ÿ…...
有哪些做策划的用的网站/seo网站推广方式
HTTP协议的下层使用的是tcp。所以我们建立一个tcp连接就能发送接收http请求。dawn底层使用了nio。可是经过dawn的封装之后,我们在编写代码的时候,就和使用普通的堵塞式socket一样 ,不须要关注nio的api。能够把我们的精力放在业务逻辑的处理上…...
武汉网站排名优化/免费网站推广方式
策略 1——停止挖掘 Law of Holes 是说当自己进洞就应该停止挖掘。对于单体式应用不可管理时这是最佳建议。换句话说,应该停止让单体式应用继续变大,也就是说当开发新功能时不应该为旧单体应用添加新代码,最佳方法应该是将新功能开发成独立微…...
湖南建设工程信息网站/今天济南刚刚发生的新闻
随着互联网web2.0网站的兴起,非关系型的数据库现在成了一个极其热门的新领域,非关系数据库产品的发展非常迅速。而传统的关系数据库在应付 web2.0网站,特别是超大规模和高并发的SNS类型的web2.0纯动态网站已经显得力不从心,暴露了…...
学校网站建设审批/新浪体育最新消息
第一步:首先在linux下添加驱动 第二步:建立Android测试代码---实现.so文件 第三步:写应用程序 问题一:android NDK jni下的c文件 Unresolved inclusion 问题二:在android 里使用JNI,总是报错:…...
模板建房多少钱一平方/seo自然排名优化
我们在iOS调试中经常会看到Clang这个,那么Clang到底是什么呢?我们来简单了解一下。 Clang是一个C、C、OC语言的轻量级编译器。源代码发布于BSD协议下。Clang是由C编写,基于LLVM,发布于LLVM BSD许可证下的编译器。它与GNU C语言规范…...