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

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) 机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许实现者保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称之为派生类&#xff1b; 继承呈现了面向对象程序设计的层次结构…...

编译安装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&#xff1a;组织形式分为三种&#xff1a; frm文件存储表结构、MyData文件存储表中的数据、MyIndex文件存储表的索引数据。是分开存储的。 Memory&#xff1a;基于内存的&#xff0c;访问速度快&#xff0…...

Golang | Leetcode Golang题解之第85题最大矩形

题目&#xff1a; 题解&#xff1a; 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操作系统的安装过程&#xff0c;并说明其中的关键步骤。 Linux操作系统的安装过程通常涉及以下几个关键步骤&#xff1a; 准备安装介质&#xff1a;需要从官网或者其他可靠来源下载Linux发行版的ISO镜像文件&#xff0c;并制作一个启动U盘或者烧录到DVD中。现在…...

中国高分辨率国家土壤信息网格基本属性数据集(2010-2018)

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

数据仓库项目---Day01

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

若依生成树表和下拉框选择树表结构(在其他页面使用该下拉框输入)

1.数据库表设计 生成树结构的主要列是id列和parent_id列&#xff0c;后者指向他的父级 2.来到前端代码生成器页面 导入你刚刚写出该格式的数据库表 3.点击编辑&#xff0c;来到字段 祖籍列表是为了好找到直接父类&#xff0c;不属于代码生成器方法&#xff0c;需要后台编…...

考研数学|李林《880》做不动,怎么办!?看这一篇!

在考研数学的备考过程中&#xff0c;遇到难题是很常见的情况&#xff0c;尤其是当你尝试解决李林880习题集中的问题时。他以其难度和深度著称&#xff0c;旨在帮助考生深入理解数学分析的复杂概念。 如果你在解题过程中感到困难&#xff0c;这并不是你个人的问题&#xff0c;而…...

paddle ocr 版面分析

教程 https://github.com/PaddlePaddle/PaddleOCR/blob/a4b7d3ba4a8333a23bab1fc1472aa18deec211d1/ppstructure/layout/README_ch.md 额外的模型&#xff0c;但是yolov2的模型缺少yml配置文件&#xff0c;找不到 https://github.com/PaddlePaddle/PaddleOCR/blob/main/ppstruc…...

25. K 个一组翻转链表 - 力扣(LeetCode)

基础知识要求&#xff1a; Java&#xff1a;方法、while循环、for循环、if else语句 Python&#xff1a; 方法、while循环、for循环、if else语句 题目&#xff1a; 给你链表的头节点 head &#xff0c;每 k 个节点一组进行翻转&#xff0c;请你返回修改后的链表。 k 是一个…...

使用 GPT-4-turbo+Streamlit+wiki+calculator构建Math Agents应用【Step by Step】

&#x1f496; Brief&#xff1a;大家好&#xff0c;我是Zeeland。Tags: 大模型创业、LangChain Top Contributor、算法工程师、Promptulate founder、Python开发者。&#x1f4dd; CSDN主页&#xff1a;Zeeland&#x1f525;&#x1f4e3; 个人说明书&#xff1a;Zeeland&…...

[240514] OpenAI 发布 GPT-4o,人机交互的历史性时刻 | 苹果芯片进军服务器剑指AI​ | 谷歌大会以AI为主

目录 OpenAI 发布 GPT-4o&#xff0c;人机交互的历史时刻苹果芯片进军服务器&#xff0c;剑指生成式 AI2024年谷歌开发者大会将围绕 AI 展开 OpenAI 发布 GPT-4o&#xff0c;人机交互的历史时刻 OpenAI 发布了 GPT-4o&#xff0c;大家一直都想要现在终于等到的语音助手 : 勿需…...

Maximo 在 Automation Script 中访问数据库

在 Automation Script 中我们通常使用 mbo 对象来操作数据&#xff0c;但有时候当数据量较大时&#xff0c;使用 mbo 对象来操作数据会比较慢。这时候&#xff0c;我们可以使用 JDBC 的方式来直接访问数据库&#xff0c;从而提高操作数据的效率。 下面看看使用 JavaScript 脚本…...

gitee 简易使用 上传文件

Wiki - Gitee.com 官方教程 1.gitee 注册帐号 (直接选择初始化选项即可&#xff0c;无需下载git&#xff09; 2.下载git 安装 http://git-scm.com/downloads 3. 桌面 鼠标右键 或是开始菜单 open git bash here 输入&#xff08;复制 &#xff0c;粘贴&#xff09; 运行…...

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

背景&#xff1a; 在我们讲wafer加工好以后&#xff0c;需要进行相关测试&#xff0c;在此阶段&#xff0c;有很多提及到的常用术语&#xff0c;我们依次进行解释。主要单词含义&#xff1a; CP &#xff1a; Chip Probing&#xff08;probe card&#xff09;&#xff0c;wafer…...

计算机vcruntime140.dll找不到如何修复,分享5种靠谱的修复教程

当您在运行某个应用程序或游戏时遇到提示“找不到vcruntime140.dll”&#xff0c;这通常意味着系统中缺少了Visual C Redistributable for Visual Studio 2015或更高版本的一个重要组件。这个错误通常发生在运行某些程序时&#xff0c;系统无法找到所需的动态链接库文件。小编将…...

超级简单的地图操作工具开发可疑应急,地图画点,画线,画区域,获取地图经纬度等

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

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

【Redis技术进阶之路】「原理分析系列开篇」分析客户端和服务端网络诵信交互实现(服务端执行命令请求的过程 - 初始化服务器)

服务端执行命令请求的过程 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 初始化服务器1. 初始化服务器状态结构初始化RedisServer变量 2. 加载相关系统配置和用户配置参数定制化配置参数案…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...

初学 pytest 记录

安装 pip install pytest用例可以是函数也可以是类中的方法 def test_func():print()class TestAdd: # def __init__(self): 在 pytest 中不可以使用__init__方法 # self.cc 12345 pytest.mark.api def test_str(self):res add(1, 2)assert res 12def test_int(self):r…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

Unity VR/MR开发-VR开发与传统3D开发的差异

视频讲解链接&#xff1a;【XR马斯维】VR/MR开发与传统3D开发的差异【UnityVR/MR开发教程--入门】_哔哩哔哩_bilibili...

麒麟系统使用-进行.NET开发

文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的&#xff0c;如果需要进行.NET开发&#xff0c;则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET&#xff0c;所以要进…...

k8s从入门到放弃之Pod的容器探针检测

k8s从入门到放弃之Pod的容器探针检测 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;容器探测是指kubelet对容器执行定期诊断的过程&#xff0c;以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...

Element-Plus:popconfirm与tooltip一起使用不生效?

你们好&#xff0c;我是金金金。 场景 我正在使用Element-plus组件库当中的el-popconfirm和el-tooltip&#xff0c;产品要求是两个需要结合一起使用&#xff0c;也就是鼠标悬浮上去有提示文字&#xff0c;并且点击之后需要出现气泡确认框 代码 <el-popconfirm title"是…...

构建Docker镜像的Dockerfile文件详解

文章目录 前言Dockerfile 案例docker build1. 基本构建2. 指定 Dockerfile 路径3. 设置构建时变量4. 不使用缓存5. 删除中间容器6. 拉取最新基础镜像7. 静默输出完整示例 docker runDockerFile 入门syntax指定构造器FROM基础镜像RUN命令注释COPY复制ENV设置环境变量EXPOSE暴露端…...