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…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
多模态大语言模型arxiv论文略读(108)
CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文标题:CROME: Cross-Modal Adapters for Efficient Multimodal LLM ➡️ 论文作者:Sayna Ebrahimi, Sercan O. Arik, Tejas Nama, Tomas Pfister ➡️ 研究机构: Google Cloud AI Re…...
搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
通过 Ansible 在 Windows 2022 上安装 IIS Web 服务器
拓扑结构 这是一个用于通过 Ansible 部署 IIS Web 服务器的实验室拓扑。 前提条件: 在被管理的节点上安装WinRm 准备一张自签名的证书 开放防火墙入站tcp 5985 5986端口 准备自签名证书 PS C:\Users\azureuser> $cert New-SelfSignedCertificate -DnsName &…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
【iOS】 Block再学习
iOS Block再学习 文章目录 iOS Block再学习前言Block的三种类型__ NSGlobalBlock____ NSMallocBlock____ NSStackBlock__小结 Block底层分析Block的结构捕获自由变量捕获全局(静态)变量捕获静态变量__block修饰符forwarding指针 Block的copy时机block作为函数返回值将block赋给…...
