C++:继承:面向对象编程的重要特性

(❁´◡❁)(●'◡'●)╰(*°▽°*)╯(*/ω\*)(^///^)(❁´◡❁)(❁´◡❁)(●'◡'●)╰(*°▽°*)╯(*/ω\*)(❁´◡❁)(●’◡’●)╰(°▽°)╯(/ω\)(///)
C++:继承:面向对象编程的重要特性
- 前言
- **继承**
- 1.继承的概念及定义
- 1.1继承的概念
- 1.2继承的定义
- 1.2.1定义的格式
- 1.2.2继承关系和访问限定符
- 1.2.3继承后基类(父类)成员访问方式的变化
- 2.基类和派生类对象赋值转换
- 3.继承中的作用域
- 4.派生类的默认成员函数
- 5.继承与友元
- 6. 继承与静态成员
- 7.多继承与菱形继承和菱形虚拟继承
🎉文章简介:
🎉本篇文章将 C++继承,全特化,偏特化,非类型模板参数,模板的分离编译 相关知识进行分享!
💕如果您觉得文章不错,期待你的一键三连哦!!!
前言
在这篇文章中,你可以学习到继承作为面向对象编程的重要特性,它允许一个类(子类)继承另一个类(父类)的属性和方法。
在文章中涵盖的主要内容:
继承的概念,继承的语法,继承的作用,单继承,多继承,菱形继承,菱形虚拟继承,菱形虚拟继承与菱形继承在内存中的差异等。
继承
1.继承的概念及定义
1.1继承的概念
继承是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。简单地说就是类的复用;
1.2继承的定义
1.2.1定义的格式
举个栗子(下附代码):

代码段:
class Person
{
protected: string _name;int _age;string _sex;int _tel;
};
class student:public Person //student继承了Person这个类
{
protected:int _id;
};
1.2.2继承关系和访问限定符

1.2.3继承后基类(父类)成员访问方式的变化
| 类成员/继承方式 | 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继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强;
举个栗子:

从上面例子可以看出,private继承后,public,protected成员在派生类可以访问,private成员不可访问;
2.基类和派生类对象赋值转换
派生类对象 可以赋值给 基类的对象 / 基类的指针 / 基类的引用。这里有个形象的说法叫切片或者切割。
基类对象不能赋值给派生类对象。
基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。注意:但是必须是基类的指针是指向派生类对象时才是安全的。这里基类如果是多态类型,会有特殊处理(后面的文章会提到);

class Person
{
protected: string _name;int _age;string _sex;int _tel;
};
class student:public Person
{
protected:int _id;
};int main()
{student s1;Person p1;p1 = s1;//s1 = p1; //这里不能基类给派生类Person& pp1 = s1; //是对截断后的内容引用Person* pp2 = &s1; //指向的是截断后的内容student* ss;ss = (student*)&p1; //基类的指针可以通过强制类型转换赋值给派生类的指针return 0;
}

3.继承中的作用域
1. 在继承体系中基类和派生类都有独立的作用域;
(就凭这一点,因此两个域中的函数不能构成函数重载)
2. 子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,可以使用 基类::基类成员 显示访问)
3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。
4. 注意在实际中在继承体系里面最好不要定义同名的成员。
4.派生类的默认成员函数
派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。(先父后子)
派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
派生类的operator=必须要调用基类的operator=完成基类的复制。
派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。(先子后父)
编译器会对析构函数名进行特殊处理,处理成destrutor(),所以父类析构函数不加virtual的情况下,子类析构函数和父类析构函数构成隐藏关系。
如果要显示调用,需要指定作用域;
5.继承与友元
友元关系不能被继承,也就是说基类友元不能访问子类私有和保护成员
举个例子:

6. 继承与静态成员
基类定义了static静态成员,则整个继承体系里面只有一个这样的成员。因为静态成员函数不是放在类里面的,而是放在静态区的,是这个类的对象所公有的,无论派生出多少个子类,都只有一个static成员实例 ;
利用这个特性,可以统计这个类被创建了多少个对象;
如果被继承了,无论派生类实例化出对象了还是基=基类实例化出对象都会调用基类的构造函数,就可以统计出个数;
例子:
class Person
{
public:Person(){_count++;}
protected: int _age;
public:static int _count;
};
int Person::_count = 0;class student:public Person
{
public:student(){}
protected:int _id;
};int main()
{student S1;student S2;Person P1;Person P2;cout << Person::_count << endl; //打印结果为4return 0;
}
7.多继承与菱形继承和菱形虚拟继承
单继承:一个子类只有一个直接父类时称这个继承关系为单继承

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

菱形继承:

菱形继承的问题:菱形继承有数据冗余和二义性的问题。在D的对象中A成员会有两份。因为B,C中都继承了A,里面各有一份A,然后D继承了B和C,所以会有两份A;
因为有两份,所以数据冗余了,又因为D里面有两份A的成员,如果想通过D实例化的对象去访问B中继承的A的成员时,不知道是去访问B的还是C的;结合下面例子看看:
结合下面代码:

class A
{
public:int _a;
};
class B:public A
{
protected:int _b;
};
class C:public A
{
protected:int _c;
};
class D:public B, public C
{
protected:int _d;
};
int main()
{D dd;//dd._a = 10; //会报错(访问不明确)dd.B::_a = 10;dd.C::_a = 100; //这样指定类域访问也可以,但是代码稍许冗余return 0;
}
解决方法:
虚拟继承可以解决菱形继承的二义性和数据冗余的问题。如上面的继承关系,在B和C的继承A时使用虚拟继承,即可解决问题。需要注意的是,虚拟继承不要在其他地方去使用。
解决后的代码:
class A
{
public:int _a;
};
class B:virtual public A /这里+
{
protected:int _b;
};
class C:virtual public A //这里+
{
protected:int _c;
};
class D:public B, public C
{
protected:int _d;
};
在哪里+virtual的问题
在造成数据冗余的那两个类的继承方式前面加virtual
比如:

菱形继承和虚拟菱形继承在内存上的差异
我们讨论的是VS上
D对象中将A放到的了对象组成的最下面,这个A同时属于B和C,那么B和C如何去找到公共的A呢?这里是通过了B和C的两个指针,指向的一张表。这两个指针叫虚基表指针,这两个表叫虚基表。虚基表中存的偏移量。通过偏移量可以找到下面的A。

(❁´◡❁)(●'◡'●)╰(*°▽°*)╯(*/ω\*)(^///^)(❁´◡❁)(●’◡’●)
相关文章:
C++:继承:面向对象编程的重要特性
(❁◡❁)(●◡●)╰(*▽*)╯(*/ω\*)(^///^)(❁◡❁)(❁◡❁)(●◡●)╰(*▽*)╯(*/ω\*)(❁◡❁)(●’◡’●)╰(▽)╯(/ω\)(///) C:继承:面向对象编程的重要特性 前言**继承**1.继承的概念及定义1.1继承的概念1.2继…...
oneMKL--FFT 基本使用
oneMKL–FFT 基本使用 本人基于官方文档的摘录与理解 oneMKL--FFT基本使用 oneMKL--FFT 基本使用1. Both FFT and Cluster FFT functions compute an FFT in five steps2 Computing an FFT2.1 缺省值2.2 Fourier Transform Funcions Code Examples2.2.1 One_dimentional In-p…...
软件测试工程师面试汇总Linux篇
Linux 命令篇 cd:切换目录 cd / #进入到系统根目录 cd . #进入到当前目录 cd .. #返回上层目录 cd /tmp #进入指定目录/tmp cd ~ #进入当前用户的家目录 2ls:列出当前目录的所有文件、文件夹(目录)信息; -l 列出目录或…...
【python】使用代理IP爬取猫眼电影专业评分数据
前言 我们为什么需要使用IP代理服务? 在编写爬虫程序的过程中,IP封锁无疑是一个常见且棘手的问题。尽管网络上存在大量的免费IP代理网站,但其质量往往参差不齐,令人堪忧。许多代理IP的延迟过高,严重影响了爬虫的工作…...
C/C++中枚举(enum)和结构体(struct)的异同
一、枚举 enum 1.普通枚举,枚举在C中使用比C使用简单 C语言: enum Color {red,green,blue }; enum Color c red;C语言 enum Color {red,green,blue }; Color c red;C认为这种枚举方式会污染名字,即:枚举使用的名字,在同一个作…...
【数据可视化】使用Python + Gephi,构建中医方剂关系网络图!
代码和示例数据下载 前言 在这篇文章中,我们将会可视化 《七版方剂学》 的药材的关系,我们将使用Python制作节点和边的数据,然后在Gephi中绘制出方剂的网络图。 Gephi是一个专门用于构建网络图的工具,只要你能提供节点和边的数…...
部署prometheus+Grafana可视化仪表盘监控服务
一、部署prometheus及监控仪表盘 简介 Prometheus是开源监控报警系统和时序列数据库(TSDB)。 Prometheus的基本原理是通过HTTP协议周期性抓取被监控组件的状态,任意组件只要提供对应的HTTP接口就可以接入监控,输出被监控组件信息的HTTP接口被叫做expo…...
python中的类与对象
前言 在Python中,类是一种用于创建新类型对象的结构,它允许我们将数据和功能(属性和方法)封装到一个单独的逻辑单元中。类可以被看作是创建对象(实例)的蓝图或模板。类(Class)和对象…...
sentry-cli - error: Failed to load .sentryclirc file from project path
Xcode 15.2 warning sentry-cli - error: Failed to load .sentryclirc file from project path (/Users/zhuhongwei/Desktop/pandabill/.sentryclirc)推荐一下刚上线的 App 熊猫小账本,里面有用到这篇博客讲的内容 熊猫小账本 一个简洁的记账 App,用于…...
回归预测 | Matlab实现SO-BP蛇算法优化BP神经网络多变量回归预测
回归预测 | Matlab实现SO-BP蛇算法优化BP神经网络多变量回归预测 目录 回归预测 | Matlab实现SO-BP蛇算法优化BP神经网络多变量回归预测预测效果基本描述程序设计参考资料 预测效果 基本描述 1.Matlab实现SO-BP蛇算法优化BP神经网络多变量回归预测(完整源码和数据) …...
如何添加 Android Native 系统服务
如何添加 Android Native 系统服务 工作学习过程中,我们可能需要去阅读不同类型的 Native 系统服务,也有可能会自己去完成一个 Native 系统服务。无论哪种情况都需要我们了解基本的 Native 如何去添加。就像我们写 Android App 得先了解一下四大组件才行…...
【力扣】189.轮转数组
题目描述 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1,2,3,4,5,6] 向右轮转 2 步: [6,7,1,2,3,4,5] 向右轮转 3 步: [5,6…...
C语言字符函数和字符串函数详解
Hello, 大家好,我是一代,今天给大家带来有关字符函数和字符串函数的有关知识 所属专栏:C语言 创作不易,望得到各位佬们的互三呦 一.字符函数 在C语言中有一些函数是专门为字符设计的,这些函数的使用都需要包含一个头文…...
【CKA模拟题】查询消耗CPU最多的Pod
题干 For this question, please set this context (In exam, diff cluster name) 对于此问题,请设置此上下文(在考试中,diff 集群名称) kubectl config use-context kubernetes-adminkubernetesFind the pod that consumes the …...
网络简略总结
目录 一、三次握手 四次挥手 1、三次握手:为了建立长链接进行交互即建立一个会话,使用http/https协议 2、四次挥手是一个断开连接释放服务器资源的过程 3、如果已经建立了连接,但是客户端突然出现故障了怎么办? 4、谁可以中断连接?客户端还是服务端还是都可以? 5、…...
如何处理错误情况
处理错误情况是确保自动窗帘系统稳定运行的重要一环。在编写代码时,你需要考虑可能发生的各种错误情况,并编写相应的错误处理代码。下面是一些处理错误情况的常见方法: (1)错误检测: 首先,你需要能够检测到错误的发生。…...
【Greenhills】MULTI IDE-GHS最新版本Compiler 23.5.4的兼容性问题
【更多软件使用问题请点击亿道电子官方网站查询】 1、 文档目标 关于GHS推出的最新编译器版本 Compiler 2023.5.4在GHS以前版本的MULTI IDE上面能否使用的问题 2、 问题场景 针对于,客户使用MULTI IDE 8.1.4以前的IDE版本,想要搭载使用最新版本的编译器…...
用连续自然数之和来表达整数 - 华为OD统一考试(C卷)
OD统一考试(C卷) 分值: 100分 题解: Java / Python / C++ 题目描述 一个整数可以由连续的自然数之和来表示。给定一个整数,计算该整数有几种连续自然数之和的表达式,且打印出每种表达式。 输入描述 一个目标整数T (1 <=T<= 1000) 输出描述 该整数的所有表达式…...
SQLiteC/C++接口详细介绍之sqlite3类(十二)
返回目录:SQLite—免费开源数据库系列文章目录 上一篇:SQLiteC/C接口详细介绍之sqlite3类(十一) 下一篇:SQLiteC/C接口详细介绍之sqlite3类(十三) 37.sqlite3_load_extension 用于在SQLit…...
linux系统--------------mysql数据库管理
目录 一、SQL语句 1.1SQL语言分类 1.2查看数据库信息 1.3登录到你想登录的库 1.4查看数据库中的表信息 1.5显示数据表的结构(字段) 1.5.1数据表的结构 1.5.2常用的数据类型: 二、关系型数据库的四种语言 2.1DDL:数据定义语言&am…...
云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?
大家好,欢迎来到《云原生核心技术》系列的第七篇! 在上一篇,我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在,我们就像一个拥有了一块崭新数字土地的农场主,是时…...
【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
【位运算】消失的两个数字(hard)
消失的两个数字(hard) 题⽬描述:解法(位运算):Java 算法代码:更简便代码 题⽬链接:⾯试题 17.19. 消失的两个数字 题⽬描述: 给定⼀个数组,包含从 1 到 N 所有…...
线程与协程
1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指:像函数调用/返回一样轻量地完成任务切换。 举例说明: 当你在程序中写一个函数调用: funcA() 然后 funcA 执行完后返回&…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
el-switch文字内置
el-switch文字内置 效果 vue <div style"color:#ffffff;font-size:14px;float:left;margin-bottom:5px;margin-right:5px;">自动加载</div> <el-switch v-model"value" active-color"#3E99FB" inactive-color"#DCDFE6"…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...
使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...
