【C++ | 继承】|概念、方式、特性、作用域、6类默认函数

继承

  • 1.继承的概念与定义
  • 2.继承的方式
      • 2.1继承基本特性
      • 2.2继承的作用域
        • 2.2.1隐藏
        • 赋值兼容
      • 派生类的创建和销毁
        • 构造函数
        • 拷贝构造
        • 赋值重载

1.继承的概念与定义

继承是面向对象编程中的一个重要概念。它的由来可以追溯到软件开发中的模块化设计代码复用的需求。

在软件开发过程中,我们经常会遇到需要为多个类添加相同的行为或属性的场景,这样就产生了代码重复的问题。为了解决这个问题,工程师们开始寻找一种方法来实现代码的复用。

继承就是一种解决代码复用问题的方式。它允许我们创建一个新的类,继承自一个已经存在的类,从而继承和复用父类的属性和方法。通过继承,我们可以在不改变父类的前提下,为子类添加额外的属性和方法,实现功能的扩展。

继承方式的由来可以追溯到早期的面向对象编程语言。早期的面向对象编程语言如Smalltalk、Simula等提供了基于类的继承机制。后来的编程语言如Java、C++等也引入了类似的继承机制。继承方式的由来和发展是为了提高软件开发的效率和可维护性,同时也体现了面向对象编程的思想和原则。

总而言之,在C++中,继承是代码复用的最重要手段。

2.继承的方式

那么我们要如何实现继承呢?
先看个样例,再看语法规则:

class parent
{
public:int _age;
};class child : public parent
{
public:int _id;
};
  • 以上就是一个简单的继承结构,child继承了parent。

  • 其中parent这种被别人继承的类叫做:基类 / 父类

  • child这种继承别人的类叫做:派生类 / 子类

  • public parent这条语句,紧跟在child的类名后面,说明child继承了parent。而public是继承方式

这个继承方式有什么作用呢?

继承方式与基类的成员访问限定符共同决定了派生类对基类成员的访问权限

基类成员 \ 继承方式public继承protect继承private继承
public成员派生类的public成员派生类的protect成员派生类的private成员
protect成员派生类的protect成员派生类的protect成员派生类的private成员
private成员不可见不可见不可见
  • 以上表格展示了所有情况下的继承,基类的成员会根据自身的访问属性以及继承方式,共同决定最终继承到派生类的成员是什么属性。

  • 其中,不可见不是指不继承,基类中的private成员继承后在派生类中不可见,就是派生类无法直接访问到这个成员,但是派生类依然是存储着这个成员的。

当然,与访问限定符一样,继承方式也是有默认方式

  • 用class定义的类,默认继承方式是private
  • 用struct定义的类,默认的继承方式是public

  • 多继承:
    一个派生类可以同时继承多个基类:
class parent1
{
public:int _age;
};class child : public parent1, public parent2
{
public:int _id;
};

2.1继承基本特性

  • 继承后,派生类有可能只增改了基类的成员函数,而成员变量是一样的,所以基类和派生类的大小可能是一样的
  • 友元关系不能继承,基类的友元不能访问子类的私有和保护成员
  • 对于基类的静态成员,派生类和基类共用,派生类不会额外创建静态成员
  • 如果不希望一个类被继承,可以将这个类的构造函数或者析构函数用private修饰
    继承后,派生类的初始化列表指向顺序为继承顺序

2.2继承的作用域

基类与派生类有两个分别独立的作用域

2.2.1隐藏

当派生类继承了基类的成员后,如果派生类自己创建了与基类同名的成员,那么派生类成员将屏蔽对同名基类成员的直接访问,这种情况叫做隐藏。

class A
{void func(){}public:int num;
};class B : public A
{void func(){}public:int num;
};

在以上继承关系中,B继承了A的num变量func函数,而B类自己还创建了同名的func与num。那么此时在B内部直接访问num与func,就是访问B自己的num。如果想要访问A的成员,需要限定作用域

B b;
b.func();//访问B的func函数
b.A::func();//访问A的func函数
  • 此外,函数重载要求两个函数在同一个作用域,而基类与派生类是两个不同作用域,所以就算参数不同也不能构成重载。所以只要基类与派生类内的函数名相同就构成隐藏,不考虑参数

赋值兼容

赋值兼容是一个基类与派生类之间的转换规则,其可以让派生类转换为父类。

以如下的继承关系做讲解:

class person
{
public:string _name;string _sex;int _age;
};class student : public person
{
public:int _No;
};

规则

派生类的对象可以赋值给基类的对象

student s;
person p = s;

赋值如下图


在这里插入图片描述


我们可以将一个派生类的成员赋值给基类成员,此时会发生一个切片效果,基类只取出派生类中属于基类的部分来构造基类。

派生类的指针可以转换为基类的指针
派生类的引用可以转换为基类的引用

student s;
person* pp = &s;
person& rp = s;

在这里插入图片描述


基类是被包含在派生类中的,所以我们用基类的指针去访问派生类,相当于只访问了基类的部分。上图中就是只访问了红色的部分。


派生类的创建和销毁

派生类是如何创建销毁的?因为派生类内部还包含了一个基类,那么基类这一部分要如何处理?
其实想要理解这一部分,就记住一句话:派生类的默认成员函数,把基类当作一个类成员变量处理

接下来我为大家讲解构造函数,拷贝构造,赋值重载,析构函数这几个与创建销毁相关的函数,来理解派生类是如何创建销毁的。

构造函数

派生类构造函数将基类当作一个成员变量,不会直接初始化基类的成员,而是通过调用基类的构造函数

在一般的类中,类内部如果有其他类的成员变量,构造函数会在初始化列表调用其构造函数。如果不直接调用,那么会隐式调用其相应的默认构造函数。

class person
{
public:string _name;
};class child : public parent
{
public:child(string name, int num):parent(name),_num(num){}
private:int _num;
};

:parent(name) 就是在初始化列表显式地调用构造函数。

拷贝构造

派生类拷贝构造将基类当作一个成员变量,不会直接拷贝基类的成员,而是通过调用基类的拷贝构造。

在一般的类中,类内部如果有其他类的成员变量,拷贝构造会在初始化列表调用其拷贝构造。如果不直接调用,那么会隐式调用其相应的默认构造函数。

class person
{
public:string _name;
};class child : public parent
{
public:child(const child& c):parent(c),_num(c.num){}
private:int _num;
};
  • parent ( c ) 就是在显式调用基类的拷贝构造,不过我们在调用基类的拷贝构造时,传入的却是派生类的引用。这是为什么?❓❔❓
  • 我们刚在赋值兼容处说过:派生类的引用可以转化为基类的引用
  • 所以此处在传参时会发生一次隐式的切片,基类的拷贝构造只访问派生类的基类部分,来拷贝出一个基类。

要注意:拷贝构造也属于构造函数,所以拷贝构造在初始化列表中如果没有显式调用拷贝构造,就会隐式调用默认构造函数


赋值重载

在派生类拷贝构造中,必须显式调用基类的赋值重载,因为赋值重载也把基类当作一个类成员做处理。赋值重载不会直接调用成员的赋值重载,而是需要我们显式调用。

class person
{
public:string _name;
};class child : public parent
{
public:child& operator=(const child& c){parent::operator=(c);_num= c._num;}
private:int _num;
};

parent::operator=(c );就是在显式地调用基类的拷贝构造,这里不能直接调用operator=(c );,因为派生类中存在operator=;这个函数,基类的函数被隐藏了,所以我们要指定作用域,来调用基类的赋值重载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/38700.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

mq消息堆积

通常情况下,出现消息积压的原因有 mq消费者挂了mq生产者生产消息的速度,大于mq消费者消费消息的速度 当数据量不大时,优化消费者处理逻辑 通过在代码中增加了一些日志,把mq消费者中各个关键节点的耗时都打印出来,发现有…

从零搭建Java酒店预订系统:实战指南_02

第四步,用户注册和登录 创建用户服务接口 在src/main/java目录下创建com.example.hotelbookingsystem.service包,并在该包下创建UserService接口: package com.example.hotelbookingsystem.service;import com.example.hotelbookingsystem.entity.User;public int…

【Android面试八股文】性能优化相关面试题: 什么是内存抖动?什么是内存泄漏?

文章目录 一、什么是内存抖动?内存抖动的问题卡顿OOM(Out Of Memory)二、什么是内存泄漏(Memory Leak)?引用计数法可达性分析法一、什么是内存抖动? 在Java中,每创建一个对象,就会申请一块内存,存储对象信息; 每分配一块内存,程序的可用内存也就少一块; 当程序…

电池企业如何通过部署PLM系统提升自身竞争力

产品生命周期管理(PLM,Product Lifecycle Management)是一种集成的企业信息化管理解决方案,旨在管理产品从概念设计、研发、生产、使用到退役的整个生命周期。PLM系统通过信息化手段,将企业的各个环节紧密连接在一起&a…

中英双语介绍美国的州:佛罗里达州(Florida)

中文版 佛罗里达州(Florida)位于美国东南部,因其温暖的气候、丰富的旅游资源和多样化的文化背景而闻名。以下是对佛罗里达州各方面的详细介绍: 人口 截至2020年,美国人口普查数据显示,佛罗里达州的人口约…

什么是协程?协程和线程的区别

文章目录 前置知识应用程序和内核阻塞和非阻塞同步和异步并发和并行IO 发展历史同步编程异步多线程/进程异步消息 回调函数(响应式编程) 协程协程基本概念go 示例代码协程和线程的区别 个人简介 前置知识 在了解协程前,我们先理解一些相关的…

强化学习原理入门-1绪论

1 绪论 1.1 这是一本什么书 强化学习算法? AlphaGo大胜世界围棋冠军李世石和柯洁事件,核心算法就用到了强化学习算法。 1.2 强化学习解决什么问题 案例1 非线性系统二级倒立摆 案例2 AlphaGo与柯洁的第二局棋 案例3 机器人学习站立 ...... 智能…

数据库被后台爆破如何解决?

在数字化时代,数据库安全成为企业与组织不容忽视的关键环节。其中,“后台爆破”攻击,即通过自动化工具尝试大量的用户名和密码组合,以非法获取数据库访问权限,是常见的安全威胁之一。本文将详细介绍如何识别、防御并解…

websocket使用,spring boot + vite + vue3

websocket使用,spring boot vite vue3 Websocket是什么WebSocket 服务端构建websocket 服务实现处理器pom文件 客户端仓库地址 Websocket是什么 WebSocket 是一种网络传输协议,可在单个 TCP 连接上进行全双工通信,位于 OSI 模型的应用层。…

沙箱在“一机两用”新规下的价值体现

在数字化时代,随着企业信息化建设的深入,数据安全问题愈发凸显其重要性。一机两用新规的出台,旨在通过技术创新和管理手段,实现终端设备的安全可控,确保敏感数据的安全存储与传输。SDC沙箱技术作为一种创新的安全防护手…

springcloud-config服务器,同样的配置在linux环境下不生效

原本在windows下能争取的获取远程配置但是部署到linux上死活都没有内容,然后开始了远程调试,这里顺带讲解下获取配置文件如果使用的是Git源,config service是如何响应接口并返回配置信息的。先说问题,我的服务名原本是abc-abc-abc…

图像基础知识入门【图像概念不同图像格式】

图像基础知识入门【图像概念&不同图像格式】 最近有在处理图像转换,因此稍微补足了一下图像相关知识,特在此记录。下面汇总是我根据自己理解和网上查阅资料而来。如有错误,欢迎大家指正。 1 基础概念 像素/分辨率 像素(Pixel)&#xff…

高德定位获取详细位置失败的处理方法

在使用高德地图定位功能获取位置信息有时候会获取详细位置失败,但是经纬度是有的,这种情况下怎么处理呢,可以使用逆地理编码通过返回的经纬度来再次获取位置信息,如果再次失败那么获取详细位置信息就失败了。 具体工具类如下: package com.demo.map.utils;import androi…

如何实现电子签名签章功能?

随着技术的发展,传统的纸质合同签署方式逐渐暴露出效率低下、存储不便和安全性不足等问题。为了解决这些问题,电子签署服务为用户提供了一个安全、高效、环保的合同管理解决方案。 电子合同管理与签署平台的核心功能 1、用户管理:平台提供用…

怎么永久禁止win10系统自动更新?一键屏蔽系统自动更新

现在 Windows 10 系统是很多办公用户的主力操作系统,可是 Windows 系统会自动更新,这会严重影响系统稳定性。因为微软虽然以提供更新为服务,但并不是每次更新它都是安全的。 接下来和我一起看看如何使用联想开发的小工具一键屏蔽系统自动更新…

MQTT协议详述

MQTT 概述 消息队列遥测传输(英语:Message Queuing Telemetry Transport,缩写:MQTT),是基于发布(Publish)/订阅(Subscribe)范式的消息协议,位于…

为什么80%的码农都做不了架构师?

文章目录 一、技术广度和深度的要求1.1 技术广度1.2 技术深度 二、全局视角和系统思维2.1 全局视角2.2 系统思维 三、沟通能力和团队合作3.1 沟通能力3.2 团队合作 四、业务理解和需求分析4.1 业务理解4.2 需求分析 五、持续学习和创新能力5.1 持续学习5.2 创新能力 六、总结 &…

【UML用户指南】-25-对高级行为建模-时间和空间

目录 1、概念 2、时间 3、位置 4、常用建模技术 4.1、对定时约束建模 4.2、对对象的分布建模 分布式系统是这样一个系统,它的构件可以物理地分布在各个结点上。 为了表达对实时系统和分布式系统建模的需要,UML 提供了定时标记、时间表达式、定时约…

抛弃 Neofetch?众多优秀替代方案等你体验!

目录 抛弃 Neofetch?众多优秀替代方案等你体验Neofetch 的替代品FastfetchscreenFetchmacchina 抛弃 Neofetch?众多优秀替代方案等你体验 NeoFetch 是用 Bash 3.2 编写的命令行系统信息工具,该项目的主要开发人员已将 GitHub 存储库存档&…