继承的相关介绍---C++
一、概念及定义
概念:
继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,继承是类设计层次的复用。
定义:
继承的格式如下:
class Student: public Person {}这里的Person是父类,也称为基类;Student是子类,也称派生类,是继承Pereson的
继承方式包括:public继承、protected继承、private继承
访问限定符包括:public访问、protected访问、private访问
如下是继承基类成员访问方式的变化:
| 类成员/继承方式 | public继承 | protected继承 | private继承 |
| 基类的public成员 | 派生类的public成员 | 派生类的protected 成员 | 派生类的private 成员 |
| 基类的protected 成员 | 派生类的protected 成员 | 派生类的protected 成员 | 派生类的private 成员 |
| 基类的private成 员 | 在派生类中不可见 | 在派生类中不可见 | 在派生类中不可 |
总结:
1. 基类private成员在派生类中无论以什么方式继承都是不可见的。这里的不可见是指基类的私有成员,但它是被继承到了派生类对象中,只是语法上限制派生类对象不管在类里面还是类外面都不能去访问它。
2. 基类private成员在派生类中是不能被访问,如果基类成员不想在类外直接被访问,但需要在派生类中能访问,就定义为protected。可以看出保护成员限定符是因继承才出现的。
3. 实际上面的表格我们进行一下总结会发现,基类的私有成员在子类都是不可见。基类的其他成员在子类的访问方式 == Min(成员在基类的访问限定符,继承方式),public > protected
> private。
4. 使用关键字class时默认的继承方式是private,使用struct时默认的继承方式是public,不过
最好显示的写出继承方式。
5. 在实际运用中一般使用都是public继承,几乎很少使用protetced/private继承,也不提倡使用protetced/private继承,因为protetced/private继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强
二、类对象赋值
1.派生类对象可以赋值给基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片或者切割。寓意把派生类中父类那部分切来赋值过去。(如下图)
2.基类对象不能赋值给派生类对象。
3.基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。这里基类如果是多态类型,可以使用RTTI(RunTime Type Information)的dynamic_cast 来进行识别后进行安全转换。

通过下面一段代码进行解释:
class Person
{protected :string _name; // 姓名string _sex; // 性别int _age; // 年龄
};
class Student : public Person
{public :int _No ; // 学号
};
void Test ()
{Student sobj ;
// 1.子类对象可以赋值给父类对象/指针/引用Person pobj = sobj ;Person* pp = &sobj;Person& rp = sobj;
//2.基类对象不能赋值给派生类对象sobj = pobj;
// 3.基类的指针可以通过强制类型转换赋值给派生类的指针pp = &sobjStudent* ps1 = (Student*)pp; // 这种情况转换时可以的。ps1->_No = 10;pp = &pobj;Student* ps2 = (Student*)pp; // 这种情况转换时虽然可以,但是会存在越界访问的问题ps2->_No = 10;
}
三、继承中的作用域
1. 在继承体系中基类和派生类都有独立的作用域。
2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)
3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。
4. 建议在实际中在继承体系里面最好不要定义同名的成员。注意:不要将重载和隐藏混淆了,重载的条件之一是要在同一作用域,而隐藏只需要满足函数名相同就能构成
四、派生类的默认成员函数
派生类一共有6个默认的成员函数,这个默认是指不用我们写,会自己生成:
这六个成员函数是如何生成的呢?
1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
3. 派生类的operator=必须要调用基类的operator=完成基类的复制。
4. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。
5. 派生类对象初始化先调用基类构造再调派生类构造。
6. 派生类对象析构清理先调用派生类析构再调基类的析构。
7. 因为后续一些场景析构函数需要构成重写,重写的条件之一是函数名相同(这个我们后面会讲解)。那么编译器会对析构函数名进行特殊处理,处理成destrutor(),所以父类析构函数不加virtual的情况下,子类析构函数和父类析构函数构成隐藏关系。
五、继承与友元、静态成员
友元关系不能继承,也就是说基类友元不能访问子类私有和保护成员
基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。无论派生出多少个子
类,都只有一个static成员实例 。
六、继承方式
继承分为:单继承、多继承和菱形继承。
单继承:一个子类只有一个直接父类时称这个继承关系为单继承

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

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

前两种继承方式都很简单,主要针对有关多继承的相关问题:请看如下代码块
class Person { public :string _name ; // 姓名 }; class Student : public Person { protected :int _num ; //学号 }; class Teacher : public Person { protected :int _id ; // 职工编号 }; class Assistant : public Student, public Teacher { protected :string _majorCourse ; // 主修课程 }; void Test () { // 这样会有二义性无法明确知道访问的是哪一个Assistant a ;a._name = "peter"; // 需要显示指定访问哪个父类的成员可以解决二义性问题,但是数据冗余问题无法解决a.Student::_name = "xxx";a.Teacher::_name = "yyy"; }可以看出菱形继承有数据冗余和二义性的问题。在Assistant的对象中Person成员会有两份。
那么要如何解决·这个问题呢?那就可以考虑到虚继承(virtural)。
虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在Student和Teacher的继承Person时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要在其他地方去使用。
class Person { public :string _name ; // 姓名 }; class Student : virtual public Person { protected :int _num ; //学号 }; class Teacher : virtual public Person { protected :int _id ; // 职工编号 }; class Assistant : public Student, public Teacher { protected :string _majorCourse ; // 主修课程 }; void Test () {Assistant a ;a._name = "peter"; }原理:
七、总结
1.public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。
2.组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象。
3.优先使用对象组合,而不是类继承 。
4.继承允许你根据基类的实现来定义派生类的实现。这种通过生成派生类的复用通常被称白箱复用(white-box reuse)。术语“白箱”是相对可视性而言:在继承方式中,基类的内部细节对子类可见 。继承一定程度破坏了基类的封装,基类的改变,对派生类有很大的影响。派生类和基类间的依赖关系很强,耦合度高。
5.对象组合是类继承之外的另一种复用选择。新的更复杂的功能可以通过组装或组合对象来获得。对象组合要求被组合的对象具有良好定义的接口。这种复用风格被称为黑箱复(black-box reuse),因为对象的内部细节是不可见的。对象只以“黑箱”的形式出现。组合类之间没有很强的依赖关系,耦合度低。优先使用对象组合有助于你保持每个类被封装。
6.实际尽量多去用组合。组合的耦合度低,代码维护性好。不过继承也有用武之地的,有些关系就适合继承那就用继承,另外要实现多态,也必须要继承。类之间的关系可以用继承,可以用组合,就用组合。
相关文章:
继承的相关介绍---C++
一、概念及定义 概念: 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结…...
Java多线程深入探讨
1. 线程与进程2. 创建和管理线程2.1. 继承Thread类2.2. 实现Runnable接口2.3 利用Callable、FutureTask接口实现。2.4 Thread的常用方法 3. 线程同步3.1. synchronized关键字3.1.1同步代码块:3.1.2 同步方法: 3.2. Lock接口 4. 线程间通信5. 线程池5.1 使…...
SpringCloud全面学习笔记之进阶篇
目录 前言微服务保护初识Sentinel雪崩问题及解决方案雪崩问题超时处理仓壁模式熔断降级流量控制总结 服务保护技术对比Sentinel介绍和安装微服务整合Sentinel 流量控制快速入门流控模式关联模式链路模式小结 流控效果warm up排队等待 热点参数限流全局参数限流热点参数限流案例…...
英语中主语从句的概念及其用法,例句(不断更新)
主语从句的原理 主语从句是一种充当整个句子主语的从句,主语从句构成的句子,是要以引导词开头的。它可以用名词性从属连词、关系代词或关系副词引导。主语从句通常位于谓语动词之前,用于表示动作、状态或事件的主体。 以下是一些常用的引导主…...
数组的子数组(亚阵列)、子序列,字符串的子串、子序列
数组 子数组 一个或连续多个数组中的元素组成一个子数组 子数组最少包含一个元素 数组 {1, 2, 3} 的子数组是 {1}, {1, 2}, {1, 2, 3}, {2}, {2, 3}, 和 {3}. 子序列 子序列就是在原来序列中找出一部分组成的序列 子序列不一定连续 相对位置还是不变 但是ÿ…...
MySQL 知识:迁移数据目录到其他路径
一、系统环境 操作系统:Centos 7 已安装环境:MySQL 8.0.26 二、开始操作 2.1 关闭SELinux 为了提高 Linux 系统的安全性,在 Linux 上通常会使用 SELinux 或 AppArmor 实现强制访问控制(Mandatory Access Control MACÿ…...
Go | 一分钟掌握Go | 8 - 并发
作者:Mars酱 声明:本文章由Mars酱编写,部分内容来源于网络,如有疑问请联系本人。 转载:欢迎转载,转载前先请联系我! 前言 当今编程界,一个好的编译型语言如果不支持并发,…...
【滤波】多元高斯
本文主要翻译自rlabbe/Kalman-and-Bayesian-Filters-in-Python的第5章节05-Multivariate-Gaussians(多元高斯)。 %matplotlib inline#format the book import book_format book_format.set_style()简介 上一篇文章中的技术非常强大,但它们只…...
单源最短路问题
全部代码 全部代码在github acwing 上 正在更新 https://github.com/stolendance/acwing 图论 欢迎大家star与fork 单源最短路问题 先用spfa算法 不行再换其他的 spfa-超级万能 说不定比dijsktra还快 dis[] 代表第k到某一点的最短距离 queue 代表刚被更新的点 它有可能更…...
Security方法注解权限控制过程及自定义权限表达式
文章目录 使用内置的权限表达式PreAuthorizePermissionEvaluator 自定义权限表达式SysMethodSecurityExpressionHandler源码流程 SysMethodSecurityExpressionRoot 使用内置的权限表达式 PreAuthorize 这个用来判断超级管理员的话,还得在表达式上加上或 Permissi…...
vue 省市县三级联动
1、 <template><div>所在省<el-select popper-class"eloption" :popper-append-to-body"true"change"getShiList(obj.province)" v-model"obj.province" placeholder"请选择所在省" clearableclear"re…...
ChatGPT实现编程语言转换
编程语言转换 对于程序员来说,往往有一类工作,是需要将一部分业务逻辑实现从服务端转移到客户端,或者从客户端转移到服务端。这类工作,通常需要将一种编程语言的代码转换成另一种编程语言的代码,这就需要承担这项工作…...
浅拷贝和深拷贝
浅拷贝: 定义:浅拷贝(Shallow Copy)是一种简单的对象复制方式,将一个对象的数据成员直接复制给另一个对象(通常是通过默认的复制构造函数或赋值运算符实现),这些数据成员可以是基本…...
进程地址空间与页表方面知识点(缺页中断及写时拷贝部分原理)
谢谢阅读,如有错误请大佬留言!! 目录 谢谢阅读,如有错误请大佬留言!! 抛出总结 开始介绍 发现问题 进程地址空间(虚拟地址) 页表 物理内存与进程地址空间映射 缺页中断基本…...
Photoshop如何使用滤镜之实例演示?
文章目录 0.引言1.将普通照片制作成油画效果2.使用液化滤镜修出完美身材3.用镜头光晕滤镜制作唯美的逆光人像4.用Camera Raw滤镜对偏色风景照进行调色 0.引言 因科研等多场景需要进行绘图处理,笔者对PS进行了学习,本文通过《Photoshop2021入门教程》及其…...
Flutter 组件抽取:日期(DatePicker)、时间(TimePicker)弹窗选择器【仿照】
简介 仿照《Flutter 仿ios自定义一个DatePicker》实行的日期弹窗选择器(DatePicker)、时间弹窗选择器(TimePicker) 效果 范例 class _TestPageState extends State<TestPage> {overridevoid initState() {super.initStat…...
基于opencv的YOLOV3对图片的目标检测
目录 1. 准备工作 2. utils 函数 2.1 plot_show 函数 2.2 get_prediction 函数 2.3 draw_bounding_box 绘制边界框函数...
Mermaid流程图
所有流程图都由节点,几何形状和边缘,箭头或线条组成。mermaid代码定义了这些节点和边缘的制作和交互方式。 它还可以容纳不同的箭头类型、多方向箭头以及与子图之间的链接。 1、流程图的方向 TB - 从上到下TD - 自上而下/与上到下相同BT - 从下到上RL -…...
国产!全志科技T507-H工业核心板( 4核ARM Cortex-A5)规格书
1核心板简介 创龙科技 SOM-TLT507 是一款基于全志科技 T507-H 处理器设计的 4 核 ARM Cortex-A 53 全国产工业核心板,主频高达 1.416GHz 。核心板 CPU 、ROM 、RAM、电源、晶振等所有元器件均采用国产工业级方案,国产化率 100%。 核心板通过邮票孔连接方式引出 MIPI CSI 、…...
java小记 2023-05-05
public class Test {/*** 谓类的方法就是指类中用static 修饰的方法(非static 为实例方法),比如main 方法,那么可以以main* 方法为例,可直接调用其他类方法,必须通过实例调用实例方法,this 关键…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...
K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》
在注意力分散、内容高度同质化的时代,情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现,消费者对内容的“有感”程度,正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中࿰…...
基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
(二)原型模式
原型的功能是将一个已经存在的对象作为源目标,其余对象都是通过这个源目标创建。发挥复制的作用就是原型模式的核心思想。 一、源型模式的定义 原型模式是指第二次创建对象可以通过复制已经存在的原型对象来实现,忽略对象创建过程中的其它细节。 📌 核心特点: 避免重复初…...

