面向对象特性中 继承详解

目录

概念:

定义:

定义格式

继承关系和访问限定符

基类和派生类对象赋值转换:

继承中的作用域:

派生类的默认成员函数

继承与友元:

继承与静态成员:

复杂的菱形继承及菱形虚拟继承:

虚拟继承使用格式

虚拟继承的原理解释

继承和组合


概念:

继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生的新类称为 派生类

继承是类设计层次的复用,之前接触的复用都是简单的函数复用。


定义:

定义格式

下图中:Person是父类,也称作基类。Student是子类,也称作派生类


继承关系和访问限定符

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

继承基类成员访问方式的变化

可以看出派生类成员访问权限是取 基类成员访问权限和派生类继承方式中较小的那个权限


基类和派生类对象赋值转换:

  • 派生类对象 可以赋值给 基类的对象/基类的指针/基类的引用,这种被称作切片或切割,派生类比基类多出的那部分将会被切除,和基类相同部分进行赋值
  • 基类对象不能赋值的派生类
  • 基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。这里基类如果是多态类型,可以使用RTTI(Run-Time Type Information)的dynamic_cast 来进行识别后进行安全转换。


继承中的作用域:

  1. 在继承体系中 基类 和 派生类 都有 独立的作用域
  2. 子类和父类中有同名成员时,子类成员将屏蔽父类会同名成员的直接访问,这种情况叫隐藏(原理就是编译器先在子类中寻找,再去父类寻找,如果子类中找到了就自然不会再去父类寻找了,所以可以使用作用域限定符直接指定父类的类域 去访问父类的同名成员)
  3. 如果是成员函数的隐藏,只需要函数名相同就构成隐藏

派生类的默认成员函数

首先,派生类一般是基类的拓展,我们可以将派生类分为 基类和拓展部分,对于基类部分的操作基本是沿用它自己的,拓展部分则是我们类似一个新类去定义

  1. 派生类的构造函数会自动调用(由编译器操作)基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
  2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
  3. 派生类的operator=必须要调用基类的operator=完成基类的复制。
  4. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。
  5. 派生类对象初始化先调用基类构造再调派生类构造。
  6. 派生类对象析构清理先调用派生类析构再调基类的析构。


继承与友元:

友元关系不能被继承,也就是说基类友元不能访问子类私有和保护成员


继承与静态成员:

基类定义了static 静态成员,则同一个继承体系中只有一个此成员。也就是说一个 static 静态成员被同一个继承体系共用,不论有多少个子类。


复杂的菱形继承及菱形虚拟继承:

单继承:一个子类只有一个直接父类时称这个继承关系为单继承

多继承:一个子类有两个或以上直接父类时称这个继承关系为多继承

菱形继承:菱形继承是多继承的一种特殊情况。

菱形继承的问题:从下面的对象成员模型构造,可以看出菱形继承有数据冗余和二义性的问题。在Assistant的对象中Person成员会有两份。

虚拟继承可以解决菱形继承的二义性和数据冗余的问题,原理下面会详细说明。如上面的继承关系,在Student和Teacher的继承Person时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要随便在其他地方去使用。


虚拟继承使用格式

在继承方式前加上 virtual 关键字即可

class A
{public:
int _a;
};// class B : public A
class B : virtual public A  //这里继承方式前面加上
{
public:
int _b;
};

虚拟继承的原理解释

上面 Person关系菱形虚拟继承的原理图:

由图可以看出,两个派生类对于同一个基类的虚拟继承,是在两派生类当中存下一个基类的偏移量指针,这个指针指向一张表,表叫做虚基表,指针叫做虚基表指针。通过这个表与存下的指针,就能找到基类的位置,所以就不会出现二义性和数据冗余的问题了。

相当于将子类 虚拟继承的成员/函数 换成对应的地址,通过这个地址找到最初的父类,这样继承的就完全是同一个东西了,不会重复也不会出现歧义


继承和组合

  • public继承是一种 is-a 的关系。也就是说每个派生类对象都是一个基类对象。
  • 组合是一种 has-a 的关系。比如 B 组合了 A,则每个 B 对象中都有一个 A 对象
  1. 优先使用对象组合,而不是类继承
  2. 继承这种通过生成派生类的复用通常被称为白箱复用,因为在继承方式中,基类的内部细节对子类是可见的,这一定程度破坏了基类的封装,基类的改变可能对派生类有很大影响(派生类的有些功能实现可能就是用基类的细节来定义的)。这样派生类和基类间的依赖关系很强,耦合度高。
  3. 组合则相反,被称为黑箱复用,被组合的对象内部细节是不可见的,其必须具有良好定义的接口,我们只需要了解其功能和接口使用即可。这样的话就被封装得很好,组合类间没有很强的依赖关系,耦合度低。
  4. 实际尽量多用组合,组合耦合度低,代码维护性好。但还是要根据实际情况,若更适合继承(is-a 的关系),就用继承。

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

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

相关文章

学MybatisPlus

1.设置MySql的数据库 spring:datasource:url: jdbc:mysql://127.0.0.1:3306/mp?useUnicodetrue&characterEncodingUTF-8&autoReconnecttrue&serverTimezoneAsia/Shanghaidriver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: MySQL123 logging:l…

IDEA搭建JDK1.8源码调试环境

大家好 下载源码 安装好 JDK 后,源码目录下面有 src.zip 文件,这个文件就是 JDK 的源码 搭建调试环境 新建 Maven 工程,包含以下文件 source:源码文件夹(手动新建)test:单元测试文件夹&…

Linux文件重定向文件缓冲区

目录 一、C文件接口 二、系统文件I/O 2.1认识系统文件I/O 2.2系统文件I/O 2.3系统调用和库函数 2.4open( )的返回值--文件描述符 2.5访问文件的本质 三、文件重定向 3.1认识文件重定向 3.2文件重定向的本质 3.3在shell中添加重定向功能 3.4stdout和stderr 3.5如何理…

JS测试框架——Jest

文章目录 安装yarn安装jestvscode支持jest的智能提示创建JS测试用例 安装yarn yarn是meta发布的一款取代npm的包管理工具。 npm install -g yarn查看yarn软件源 yarn config get registry换源 yarn config set registry https://registry.npmmirror.com恢复官方源 yarn co…

中广核CGN25届校招网申SHL测评题库、面试流程、招聘对象,内附人才测评认知能力真题

​中国广核集团校园招聘在线测评攻略🚀 🎓 校园招聘对象 2024届、2025届海内外全日制应届毕业生,大专、本科、硕士、博士,广核集团等你来! 📈 招聘流程 投递简历 简历筛选 在线测评(重点来啦…

个人项目简单https服务配置

1.SSL简介 SSL证书是一种数字证书,由受信任的证书颁发机构(CA)颁发,用于在互联网通信中建立加密链接。SSL代表“安全套接层”,是用于在互联网上创建加密链接的协议。SSL证书的主要目的是确保数据传输的安全性和隐私性…

看Threejs好玩示例,学习创新与技术(LiquidRaymarching)

今天的示例有点超出我的想象,首先会科普下WGSL这种新的着色器脚本,然后说说示例《Liquid Raymarching Scene with Three.js Shading Language | Codrops (tympanus.net)》的技术流程。本示例最终呈现的效果如下。可以看到他跟QQ那个消息拖拽消灭的效果非…

基于STM32的数字温度传感器设计与实现

引言 STM32 是由意法半导体(STMicroelectronics)开发的基于 ARM Cortex-M 内核的微控制器系列,以其强大的处理能力、丰富的外设接口和低功耗著称,广泛应用于嵌入式系统设计中。在这篇文章中,我们将介绍如何基于 STM32…

考研论坛平台|考研论坛小程序系统|基于java和微信小程序的考研论坛平台小程序设计与实现(源码+数据库+文档)

考研论坛平台小程序 目录 基于java和微信小程序的考研论坛平台小程序设计与实现 一、前言 二、系统功能设计 三、系统实现 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取: 博主介绍:✌️大厂…

联想电脑怎么开启vt_联想电脑开启vt虚拟化教程(附intel和amd主板开启方法)

最近使用联想电脑的小伙伴们问我,联想电脑怎么开启vt虚拟。大多数可以在Bios中开启vt虚拟化技术,当CPU支持VT-x虚拟化技术,有些电脑会自动开启VT-x虚拟化技术功能。而大部分的电脑则需要在Bios Setup界面中,手动进行设置&#xff…

【Android】Handler消息机制

文章目录 前言概述核心组件概述Android消息机制概述 Android消息机制分析ThreadLocal的工作原理ThreadLocal基础ThreadLocal实现原理 MessageQueueLooperHandler的工作原理总结 前言 本文用于记录Android的消息机制,主要是指Handler的运行机制。部分内容参考自《An…

数据库管理-第248期 23ai:全球分布式数据库-分片数据分布方法(20241006)

数据库管理248期 2024-10-06 数据库管理-第248期 23ai:全球分布式数据库-分片数据分布方法(20241006)1 系统管理分片2 用户定义分片2.1 分片空间2.2 在用户定义分片配置中添加分片空间2.3 为用户定义分片创建表空间2.4 用户定义分片创建分片表…

使用bert模型进行命名实体识别任务

一、实验内容 本实验使用预训练的 BERT 模型进行命名实体识别(NER)任务,并且使用 Hugging Face 的 Transformers 库完成模型的训练、验证和测试。最后,使用测试集评估模型性能,计算NER指标。 二、算法介绍 Bert是一种…

Python技巧:如何处理未完成的函数

一、问题的提出 写代码的时候,我们有时候会给某些未完成的函数预留一个空位,等以后有时间再写具体内容。通常,大家会用 pass 或者 ... (省略号)来占位。这种方法虽然能让代码暂时不报错,但可能在调试的时候…

毕业设计 深度学习水果识别

文章目录 1 前言2 开发简介3 识别原理3.1 传统图像识别原理3.2 深度学习水果识别 4 数据集5 部分关键代码5.1 处理训练集的数据结构5.2 模型网络结构5.3 训练模型 6 识别效果 1 前言 Hi,大家好,这里是丹成学长,今天做一个 基于深度学习的水果…

《如何高效学习》

有道云笔记 第一部分 整体性学习策略 结构 结构就像思想中的一座城市,有很多建筑物,建筑物之间有道路相连,有高大而重要的与其他建筑有上百条路相连,无关紧要的建筑只有少数泥泞的小道与外界相通。 建立良好的知识结构就是绘制…

[ 蓝桥 ·算法双周赛 ] 第 19 场 小白入门赛

&#x1f525;博客介绍&#xff1a; EvLast &#x1f3a5;系列专栏&#xff1a; <<数据结构与算法>> << 算法入门>> << C项目>> &#x1f3a5; 当前专栏: << 算法入门>> 专题 : 帮助小白快速入门算法竞赛 &#x1f44d…

Golang | Leetcode Golang题解之第457题环形数组是否存在循环

题目&#xff1a; 题解&#xff1a; func circularArrayLoop(nums []int) bool {n : len(nums)next : func(cur int) int {return ((curnums[cur])%n n) % n // 保证返回值在 [0,n) 中}for i, num : range nums {if num 0 {continue}slow, fast : i, next(i)// 判断非零且方…

ARM(5)内存管理单元MMU

一、虚拟地址和物理地址 首先&#xff0c;计算机系统的内存被组成一个由M个连续的字节大小组成的数组。每字节都会有一个唯一的物理地址。CPU访问内存最简单的方式就是使用物理地址。如下图&#xff1a; 图 1 物理地址,物理寻址 而现在都是采用的都是虚拟寻址的方法。CPU生成一…

复习HTML(基础)

目录 HTML含义 HTML作用 HTML的常用元素 元素的特点 元素的分类 1 是否嵌套关系 2 是否独占一行 块元素&#xff1a;独占一行 行内元素&#xff1a;共享一行 行内元素与块级元素的转换 3是否有结束标签 常用标签 1 标题标签&#xff1a;有六级 我们用h1 ~h6 表…