C++基础——继承(上)
一、继承的概念
继承 (inheritance) 机制是面向对象程序设计使代码可以复用的最重要的手段,它允许实现者保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称之为派生类;
继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程;
以前,我们接触的复用都是函数复用,继承是类设计层次的复用。
继承所表达的是类之间相关的关系,这种关系使得对象可以继承另外一类对象的特征和能力。
继承的作用:避免公用代码的重复开发,减少代码和数据冗余。
二、继承关系
继承基类成员访问方式的变化
三种继承方式代码示例:
//基类
class A
{
public:int mA;
protected:int mB;
private:int mC;
};//1. 公有(public)继承
class B : public A{
public:void PrintB(){cout << mA << endl; //可访问基类public属性cout << mB << endl; //可访问基类protected属性//cout << mC << endl; //不可访问基类private属性}
};
class SubB : public B{void PrintSubB(){cout << mA << endl; //可访问基类public属性cout << mB << endl; //可访问基类protected属性//cout << mC << endl; //不可访问基类private属性}
};
void test01(){B b;cout << b.mA << endl; //可访问基类public属性//cout << b.mB << endl; //不可访问基类protected属性//cout << b.mC << endl; //不可访问基类private属性
}//2. 私有(private)继承
class C : private A{
public:void PrintC(){cout << mA << endl; //可访问基类public属性cout << mB << endl; //可访问基类protected属性//cout << mC << endl; //不可访问基类private属性}
};
class SubC : public C{void PrintSubC(){//cout << mA << endl; //不可访问基类public属性//cout << mB << endl; //不可访问基类protected属性//cout << mC << endl; //不可访问基类private属性}
};
void test02(){C c;//cout << c.mA << endl; //不可访问基类public属性//cout << c.mB << endl; //不可访问基类protected属性//cout << c.mC << endl; //不可访问基类private属性
}
//3. 保护(protected)继承
class D : protected A{
public:void PrintD(){cout << mA << endl; //可访问基类public属性cout << mB << endl; //可访问基类protected属性//cout << mC << endl; //不可访问基类private属性}
};
class SubD : public D{void PrintD(){cout << mA << endl; //可访问基类public属性cout << mB << endl; //可访问基类protected属性//cout << mC << endl; //不可访问基类private属性}
};
void test03(){D d;//cout << d.mA << endl; //不可访问基类public属性//cout << d.mB << endl; //不可访问基类protected属性//cout << d.mC << endl; //不可访问基类private属性
}
而以上三种继承方式,对于基类的私有成员(成员属性/成员方法)在派生类中不可见,即不论在派生类的类外还是类内都不可以访问:
三、继承方式总结
基类 private 成员在派生类中无论以什么方式继承都是不可见的。 这里的不可见指的是基类的私有成员虽然被继承到了派生类对象中,但是语法上限制了派生类对象访问它,无论是在派生类的类内还是类外,都无法访问;
如果基类成员不想让派生类在类外访问,但需要让派生类类内可以访问,那么该基类成员就可以定义为 protected,可以看到,protected 在继承角度有着很大的存在意义;
我们总结一下就会发现,除开基类的私有成员,基类的其他成员被子类继承后的访问方式 == Min (基类成员的访问限定符, 继承方式),private < protected < public;
class 的默认继承方式是 private,struct 的默认继承方式是public,但实际中,最好显示声明继承方式;
事实上,大多数的实际运用中,public 继承占绝大多数, 几乎很少使用 protected/private 继承,也不提倡 protected/private 继承, 因为 protected/private 继承下来的成员只能在派生类的类内使用,实际中扩展性并不强。
四、派生类的默认成员函数
默认成员函数即便我们不写,编译器也会自动生成一份,那么在派生类中,这些成员函数如何处理呢?
- 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员,如果基类没有默认的构造函数,则必须在派生类的构造函数的初始化列表阶段显式初始化基类的成员属性;
- 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类成员属性的初始化;
- 派生类的 operator= 必须要调用基类的 operator= 完成基类成员属性的赋值;
- 派生类的析构函数会在调用完成后自动调用基类的析构函数清理基类成员属性,因为这样才能保证派生类对象先清理派生类的成员属性再清理基类的成员属性;
- 派生类对象初始化资源时 (调用构造),先初始化基类成员属性,后初始化派生类成员属性;
- 派生类对象清理资源时 (调用析构),先清理派生类资源,在清理基类资源,即先调用派生类析构,然后编译器自动调用基类析构;
- 我们知道,重写的条件之一是函数名相同,可是基类和派生类的析构函数的函数名不相同啊,实际上,当派生类继承基类后,编译器会对析构函数进行特殊处理,析构函数的函数名统一为 destructor,所以,如果基类的析构函数不是虚函数,那么基类析构函数和父类析构函数构成隐藏关系。
我们一共学过六个默认成员函数:
1.派生类的构造函数
实例化一个派生类的对象后,结果却调用了基类的构造;
如果此时基类没有默认构造,那么实例化派生类对象时,会发生编译报错。
因此,实现者往往需要自己显式定义派生类的构造函数。
对于派生类的构造函数来说:
- 对于派生类的成员属性,跟以前的处理方式一样( 对于内置类型不处理,对于自定义类型调用它的默认构造函数 );
- 对于基类的成员属性,必须调用基类的构造函数初始化。
2.派生类的拷贝构造
对于派生类的拷贝构造来说:
- 对于派生类成员属性,跟以前的处理方式一样( 对于内置类型按照字节序的方式进行拷贝,对于自定义类型调用它的拷贝构造函数 );
- 对于基类成员属性,必须调用基类的拷贝构造函数初始化基类成员属性;
对于继承的基类成员而言,需要调用基类的拷贝构造初始化基类的成员属性。
3.派生类的赋值运算符重载
对于派生类来说,编译器默认生成的赋值运算符重载会:
- 对于自己本身的成员,跟以前的处理方式一样(对于内置类型按照字节序的方式进行拷贝,对于自定义类型调用它的赋值运算符重载);
- 对于继承父类的成员,必须调用父类的赋值运算符重载;
编译器默认生成的赋值运算符重载会调用父类的赋值运算符重载;
4.派生类的析构函数
对于派生类来说,编译器默认生成的析构函数,分两种情况:
- 对于自身的成员,对内置类型不处理,对自定义类型去调用它的析构函数,根以前一样;
- 对于继承的成员,需要去调用父类的析构函数处理。
而对于派生类来说,它需要保证:
派生类对象初始化时,基类成员先初始化 (先调用基类构造),派生类成员后初始化 (后调派生类构造);
派生类对象清理时,派生类成员先释放资源 (先调用派生类析构),基类成员后释放资源 (后调用基类析构);
因此编译器为了确保这种顺序,会自动调用基类的析构函数,不需要我们显式调用基类的析构函数。
5.取地址重载和const取地址重载
这两个函数跟以前一样,不需要做特殊处理,一般情况下我们也没必要显示实现;
四、继承与友元
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员。
class worker;
// 基类
class person
{
public:friend void display(const person& pobj, const worker& wobj);
protected:string _name = "haha";
};
// 派生类
class worker : public person
{
protected:string _job_number = "111";
};void display(const person& pobj, const worker& wobj)
{cout << pobj._name << endl;cout << wobj._job_number << endl;
}void Test1(void)
{person pobj;worker wobj;display(pobj, wobj);
}
这段代码编译器会报错,提示 wobj._job_number 不可访问;
总而言之, 友元关系不可以从基类继承到派生类中,并且友元要慎用且不宜多用。
相关文章:

C++基础——继承(上)
一、继承的概念 继承 (inheritance) 机制是面向对象程序设计使代码可以复用的最重要的手段,它允许实现者保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称之为派生类; 继承呈现了面向对象程序设计的层次结构…...
编译安装Python3
1、源码安装 1、安装依赖软件包 yum -y install gcc gcc-c zlib-devel bzip2-devel openssl-devel sqlite-devel readline-devel libffi-devel # python3.7版本安装 2、下载 curl -o python3.6.5.tgz https://www.python.org/ftp/python/3.6.5/Python-3.6.5.tgz // 或者 w…...

MySQL数据库核心面试题
数据库中的引擎 常用的引擎有InnoDB、MyIsam、Memory三种。 MyIsam:组织形式分为三种: frm文件存储表结构、MyData文件存储表中的数据、MyIndex文件存储表的索引数据。是分开存储的。 Memory:基于内存的,访问速度快࿰…...

Golang | Leetcode Golang题解之第85题最大矩形
题目: 题解: func maximalRectangle(matrix [][]byte) (ans int) {if len(matrix) 0 {return}m, n : len(matrix), len(matrix[0])left : make([][]int, m)for i, row : range matrix {left[i] make([]int, n)for j, v : range row {if v 0 {continu…...
Linux基础知识面试题
1. 请描述Linux操作系统的安装过程,并说明其中的关键步骤。 Linux操作系统的安装过程通常涉及以下几个关键步骤: 准备安装介质:需要从官网或者其他可靠来源下载Linux发行版的ISO镜像文件,并制作一个启动U盘或者烧录到DVD中。现在…...

中国高分辨率国家土壤信息网格基本属性数据集(2010-2018)
中国高分辨率国家土壤信息网格基本属性数据集(2010-2018) 数据介绍 土壤是人类生存和发展的基础,多个联合国可持续发展目标(SDGs)与土壤资源利用和管理直接相关。然而,全球和我国现有土壤信息大多源于历史土…...

数据仓库项目---Day01
文章目录 框架的安装包数据仓库概念项目需求及架构设计项目需求分析项目框架技术选型系统数据流程设计框架版本选型集群资源规划设计 数据生成模块数据埋点主流埋点方式埋点数据上报时机 服务器和JDK准备搭建三台Linux虚拟机(VMWare)编写集群分发脚本xsyncSSH无密登录配置JDK准…...

若依生成树表和下拉框选择树表结构(在其他页面使用该下拉框输入)
1.数据库表设计 生成树结构的主要列是id列和parent_id列,后者指向他的父级 2.来到前端代码生成器页面 导入你刚刚写出该格式的数据库表 3.点击编辑,来到字段 祖籍列表是为了好找到直接父类,不属于代码生成器方法,需要后台编…...

考研数学|李林《880》做不动,怎么办!?看这一篇!
在考研数学的备考过程中,遇到难题是很常见的情况,尤其是当你尝试解决李林880习题集中的问题时。他以其难度和深度著称,旨在帮助考生深入理解数学分析的复杂概念。 如果你在解题过程中感到困难,这并不是你个人的问题,而…...
paddle ocr 版面分析
教程 https://github.com/PaddlePaddle/PaddleOCR/blob/a4b7d3ba4a8333a23bab1fc1472aa18deec211d1/ppstructure/layout/README_ch.md 额外的模型,但是yolov2的模型缺少yml配置文件,找不到 https://github.com/PaddlePaddle/PaddleOCR/blob/main/ppstruc…...

25. K 个一组翻转链表 - 力扣(LeetCode)
基础知识要求: Java:方法、while循环、for循环、if else语句 Python: 方法、while循环、for循环、if else语句 题目: 给你链表的头节点 head ,每 k 个节点一组进行翻转,请你返回修改后的链表。 k 是一个…...

使用 GPT-4-turbo+Streamlit+wiki+calculator构建Math Agents应用【Step by Step】
💖 Brief:大家好,我是Zeeland。Tags: 大模型创业、LangChain Top Contributor、算法工程师、Promptulate founder、Python开发者。📝 CSDN主页:Zeeland🔥📣 个人说明书:Zeeland&…...
[240514] OpenAI 发布 GPT-4o,人机交互的历史性时刻 | 苹果芯片进军服务器剑指AI | 谷歌大会以AI为主
目录 OpenAI 发布 GPT-4o,人机交互的历史时刻苹果芯片进军服务器,剑指生成式 AI2024年谷歌开发者大会将围绕 AI 展开 OpenAI 发布 GPT-4o,人机交互的历史时刻 OpenAI 发布了 GPT-4o,大家一直都想要现在终于等到的语音助手 : 勿需…...
Maximo 在 Automation Script 中访问数据库
在 Automation Script 中我们通常使用 mbo 对象来操作数据,但有时候当数据量较大时,使用 mbo 对象来操作数据会比较慢。这时候,我们可以使用 JDBC 的方式来直接访问数据库,从而提高操作数据的效率。 下面看看使用 JavaScript 脚本…...

gitee 简易使用 上传文件
Wiki - Gitee.com 官方教程 1.gitee 注册帐号 (直接选择初始化选项即可,无需下载git) 2.下载git 安装 http://git-scm.com/downloads 3. 桌面 鼠标右键 或是开始菜单 open git bash here 输入(复制 ,粘贴) 运行…...
iOS Xcode 升级Xcode15报错: SDK does not contain ‘libarclite
一 iOS Xcode 升级Xcode15报错: SDK does not contain libarclite 1.1 报错信息 SDK does not contain libarclite at the path /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/ lib/arc/libarclite_iphonesimulator.a; try increasin…...

即插即用篇 | YOLOv8引入轴向注意力 Axial Attention | 多维变换器中的轴向注意力
本改进已集成到 YOLOv8-Magic 框架。 我们提出了Axial Transformers,这是一个基于自注意力的自回归模型,用于图像和其他组织为高维张量的数据。现有的自回归模型要么因高维数据的计算资源需求过大而受到限制,要么为了减少资源需求而在分布表达性或实现的便捷性上做出妥协。相…...
【芯片制造】【常用术语】CP、FT、WAT
背景: 在我们讲wafer加工好以后,需要进行相关测试,在此阶段,有很多提及到的常用术语,我们依次进行解释。主要单词含义: CP : Chip Probing(probe card),wafer…...

计算机vcruntime140.dll找不到如何修复,分享5种靠谱的修复教程
当您在运行某个应用程序或游戏时遇到提示“找不到vcruntime140.dll”,这通常意味着系统中缺少了Visual C Redistributable for Visual Studio 2015或更高版本的一个重要组件。这个错误通常发生在运行某些程序时,系统无法找到所需的动态链接库文件。小编将…...

超级简单的地图操作工具开发可疑应急,地图画点,画线,画区域,获取地图经纬度等
使用echars的地图画点,画线,画区域,获取地图经纬度等 解压密码:10086007 地图也是用临时的bmap.js和china.js纯离线二选一 一共就这么多文件 画点,画线,画区域 点击地图获取经纬度-打印到控制台,这样就能渲染航迹,多变形,结合其他算法算圆等等操作 下载资源:https://download…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...

智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/
使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题:docker pull 失败 网络不同,需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...