六、继承(一)

news2024/12/18 22:19:59

1 继承的引入

以往我们想分别实现描述学生、老师的类,可能会这样子做:

class Student
{
	string _name;
    string _number;
	int _tel;
	int id;
	string _address;
	int _age;
};
class Teacher
{
	string _name;
    int _level;
	int _tel;
	int id;
	string _address;
	int _age;
};

但从这两个类的结构可以看到它们的内容是高度重复的,有没有什么办法能将几个类公共的部分提取出来,又能保留其独有的特性呢?

这就要用到C++的继承机制。

2 继承的概念及定义

2.1 继承的概念

继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持原有类特性的基础上进行扩展,增加功能,这样产生新的类,称派生类。继承呈现了面向对象程序设计的层次结构,体现了由简单到复杂的认知过程。以前我们接触的复用都是函数复用,而继承是类设计层次的复用

例:

#include <iostream>
#include <string>
using namespace std;
class Person//父类Person
{
public:
	void Print()
	{
		cout << "name:" << _name << endl;
		cout << "age:" << _age << endl;
	}
protected:
	string _name = "peter"; //姓名
	int _age = 18;  //年龄
};

class Student : public Person//子类Student
{
protected:
	int _stuid; //学号
};

class Teacher : public Person//子类Teacher
{
protected:
	int _jobid; //工号
};
int main()
{
	Student s;
	Teacher t;
	s.Print();
	t.Print();
	return 0;
}

运行结果:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

从运行结果可以看到,继承后父类的Person的成员(成员函数和成员变量)都会变成子类的一部分,这里体现出了StudentTeacher复用了Person的成员。

2.2 继承的定义

2.2.1 继承的定义格式

我们以刚才的例子为例,讲解一下继承的定义格式。

//     派生类    继承方式  基类
         |         |      |
         |         |      |
class Student : public Person
{
protected:
	int _stuid;
};
2.2.2 继承关系和访问限定符

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.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继承下来的成员都只能在派生类的类里面使用,实际中扩展维护性不强。

例:

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

3.1 基类和派生类对象赋值转换引入

我们先来看下面这段代码:

double d = 1.1;
int i = d;

以前我们说d要赋值给i会产生一个具有常性的临时变量,这是隐式类型转换。

那么现在有这样一个问题:

Student s;
Person p = s;

在公有继承下,一个派生类的对象能不能赋给一个基类的对象呢?

这就涉及到基类和派生类对象间的赋值转换。

3.2 基类和派生类对象赋值转换的规则

在公有继承下,基类和派生类对象间赋值转换需遵守以下规则:

  1. 派生类对象可以赋值给基类的对象基类的指针基类的引用,这里有个形象的说法叫切片或者切割,寓意把派生类中基类那部分切下来赋值过去。

  2. 基类对象不能赋值给派生类对象。

  3. 基类的指针或者引用可以通过强制类型转换赋值给派生类的指针或者引用。但是必须是基类的指针是指向派生类对象时才是安全的。这里基类如果是多态类型,可以使用RTTI(RunTime Type Information)dynamic_cast识别后进行安全转换,这里先了解即可,后续会讲解。

4 继承中的作用域

  1. 在继承体系中基类和派生类都有独立的作用域。
  2. 如果子类和父类中有同名成员,那么子类成员将屏蔽父类对同名成员的直接访问,这种情况叫隐藏,也叫重定义。(在子类成员函数中,可以使用基类::基类成员来进行显示访问)
  3. 需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏。
  4. 在实际中,在继承体系里面最好不要定义同名的成员。

5 派生类的默认成员函数

之前我们说过,每一个类都有6个默认成员函数,这个“默认”指的是如果我们自己不写编译器就会自动生成。

而在派生类中,这几个成员函数的生成遵循以下规则:

  1. 派生类的构造函数必须调用基类的构造函数初始化基类的那一部分成员。如果基类没有默认的构造函数,则必须在派生类构造函数的初始化列表阶段显示调用。
  2. 派生类的拷贝构造函数必须调用基类的拷贝构造完成基类的拷贝初始化。
  3. 派生类的operator=必须要调用基类的operator=完成基类的复制。
  4. 派生类的析构函数会在被调用完成后自动调用基类的析构函数清理基类成员。因为这样才能保证派生类对象先清理派生类成员再清理基类成员的顺序。
  5. 派生类对象初始化先调用基类构造再调派生类构造。
  6. 派生类对象析构清理先调用派生类析构再调用基类的析构。
  7. 因为后续一些场景析构函数需要构成重写,而重写的条件之一是函数名相同,所以编译器会对析构函数名进行特殊处理,处理成destrutor(),所以父类析构函数不加virtual的情况下,子类析构函数和父类析构函数构成隐藏关系,这一点在后续会进行讲解。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

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

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

相关文章

数据中台:数字中国战略关键技术实施

这里写目录标题 前言为何要建设数据中台数据中台建设痛点数据中台学习资料聚焦前沿&#xff0c;方法论体系更新与时俱进&#xff0c;紧跟时代热点深入6大行业&#xff0c;提炼实践精华大咖推荐&#xff0c;数字化转型必备案头书 前言 在数字中国这一国家战略的牵引下&#xff0…

软考56-上午题-【数据库】-数据库设计步骤2

一、回顾&#xff1a;数据库设计的步骤 1、用户需求分析&#xff1a;手机用户需求&#xff0c;确定系统边界&#xff1b; 2、概念设计&#xff08;概念结构设计&#xff09;&#xff1a;是抽象概念模型&#xff0c;较理想的是采用E-R方法。 3、逻辑设计&#xff1a;E-R图——…

在四维轻云平台的使用过程中,遇到这些问题应该怎么办?

「四维轻云」是一款轻量化的地理空间数据管理云平台&#xff0c;支持地理空间数据的在线管理、编辑及分享。那么&#xff0c;在四维轻云平台的使用过程中&#xff0c;遇到这些问题应该怎么办&#xff1f; 1、启动插件后&#xff0c;上传界面仍提示“请启动插件” 请先升级插件…

IDEA类和方法注释模板设置

一、概述 IDEA自带的注释模板不是太好用&#xff0c;我本人到网上搜集了很多资料系统的整理了一下制作了一份比较完整的模板来分享给大家&#xff0c;我不是专业玩博客的&#xff0c;写这篇文章只是为了让大家省事。 这里设置的注释模板采用Eclipse的格式&#xff0c;下面先贴…

十五 超级数据查看器 讲解稿 外观设置

十五 超级数据查看器 讲解稿 外观设置 视频讲座地址 讲解稿全文: 大家好&#xff0c;今天讲解超级数据查看器,详情界面的外观设置。 首先&#xff0c;我们打开超级数据查看器。 本节课以成语词典为例来做讲述。 我们打开成语词典这个表&#xff0c;随便选一条记录点击&#x…

导轨安装模拟量直流信号隔离转换放大器0-±5V/0-±10V/0-10V/0-20mA/4-20mA/0-±10mA/0-±20mA

概述&#xff1a; 导轨安装DIN11 IPO EM系列模拟信号隔离放大器是一种将输入信号隔离放大、转换成按比例输出的直流信号混合集成电路。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等需要电量隔离测控的行业。该模块内部嵌入了一个高效微功率的电源&#xff0…

kettle下载及安装

JDK下载 安装kettle之前需要安装JDK JDK下载链接&#xff1a;JDK下载 配置环境变量&#xff1a; 新建系统变量&#xff1a;变量值为JDK安装路径 Path新增&#xff1a; kettle下载 链接地址&#xff1a;PDI&#xff08;kettle&#xff09; 点击下载 同意 Click here to a…

python和nodejs一键安装当前项目所有依赖

python和nodejs一键安装当前项目所有依赖。群里有人问怎么快速安装网上下载的源码里面的依赖。所以在这里分享一下。更多问题可以自己加群917400262问我。 目录导航 1.0 python一键安装当前项目所有依赖2.0 nodejs一键安装当前项目所有依赖 1.0 python一键安装当前项目所有依赖…

Java数据结构-----ArrayList与顺序表

目录 一、线性表 二、顺序表 接口的实现 三、ArrayList简介 四、 ArrayList使用 1. ArrayList的构造 2.ArrayList常见操作 3. ArrayList的遍历 4.ArrayList的扩容机制 五、ArrayList的具体使用 简单的洗牌算法 一、线性表 线性表&#xff08;linear l…

WordPress上传图片错误:不是合法的JSON响应

最近在进行WordPress迁移至新服务器的过程中&#xff0c;遭遇到一个棘手的问题&#xff0c;即在编辑文章并上传图片时&#xff0c;不断遭遇“此响应不是合法的JSON响应”的错误。经过多次验证和搜索&#xff0c;最终确定问题的根本原因并不在于禁用 Gutenberg 编辑器或安装经典…

ensp路由启动失败41错误及ensp安装【附安装包】(亲测!!!)

我用夸克网盘分享了 「eNSP安装教程&#xff08;非常详细&#xff09;从零基础入门到精通&#xff0c;看完这一篇就够了【附安装包】_ensp下载安装教程-CSDN博客.pdf」&#xff0c;点击链接即可保存。打开「夸克APP」在线查看&#xff0c;支持多种文档格式转换。 链接&#xf…

神经网络结构——CNN、RNN、LSTM、Transformer !!

文章目录 前言 一、什么是CNN 网络结构 解决问题 工作原理 实际应用 二、什么是RNN 网络结构 解决问题 工作原理 应用场景 三、什么是LSTM 网络结构 解决问题 工作原理 应用场景 四、什么是Transformer 网络结构 解决问题 工作原理 BERT GPT 前言 本文将从什么是CNN&#xff1…

现货黄金交易商运作模式大解密

也许现货黄金投资者都知道自己需要通过交易平台才能进入市场买卖&#xff0c;但很多人却并不知道交易平台如何处理自己的交易订单。其实交易商主要分为四种类型&#xff1a;交易员平台、无交易员平台、直接处理式平台以及电子通信网络平台&#xff0c;本文将为大家介绍一下它们…

WP外贸营销型网站模板

WordPress外贸独立站主题 简洁实用的WordPress外贸独立站主题&#xff0c;适合时尚服装行业搭建wordpress企业官网使用。 零件配件WordPress外贸建站模板 汽车行业零配件WordPress外贸建站模板&#xff0c;卖配件、零件的外贸公司可以使用的WordPress主题。 https://www.jia…

李沐动手学习深度学习——3.5练习

减少batch_size&#xff08;如减少到1&#xff09;是否会影响读取性能&#xff1f; 肯定会影响&#xff0c;计算机io性能而言&#xff0c;随着batch_size增大&#xff0c;读取越来越快&#xff0c;需要的时间越少。这里会涉及到计算机操作系统的知识点&#xff0c;内存与硬盘之…

获取 Windows 通知中心弹窗通知内容(含工具汉化)

目录 前言 技术原理概述 测试代码和程序下载连接 本文出处链接&#xff1a;https://blog.csdn.net/qq_59075481/article/details/136440280。 前言 从 Windows 8.1 开始&#xff0c;Windows 通知现在以 Toast 而非 Balloon 形式显示&#xff08; Bollon 通知其实现在是应用…

ARM总结and复习

安装交叉编译工具链 a. 为什么安装 因为arm公司的指令集在不断迭代升级&#xff0c;指令集日益增多,而架构是基于指令集研发的&#xff0c;所以架构不一样&#xff0c;指令集也不一样 eg:arm架构使用的是arm指令集 x86架构使用的是x86指令集 而我们日常开发环境中linux的架构…

QueryDet代码解析

配置文件 # 表示该配置文件是基于另一个配置文件BaseRetina.yaml进行扩展和覆盖的 _BASE_: "../BaseRetina.yaml" # 指定输出目录&#xff0c;训练过程中的日志、模型权重和评估结果将保存在该目录下。 OUTPUT_DIR: "work_dirs/visdrone_querydet" # 指定…

前端面试 跨域理解

2 实现 2-1 JSONP 实现 2-2 nginx 配置 2-2 vue 开发中 webpack自带跨域 2 -3 下载CORS 插件 或 chrome浏览器配置跨域 2-4 通过iframe 如&#xff1a;aaa.com 中读取bbb.com的localStorage 1)在aaa.com的页面中&#xff0c;在页面中嵌入一个src为bbb.com的iframe&#x…

Mybatis批量更新对象数据的两种方法

说明&#xff1a;遇到一次需要批量修改对象的场景。传递一个对象集合&#xff0c;需要根据对象ID批量修改数据库数据&#xff0c;使用的是MyBatis框架。查了一些资料&#xff0c;总结出两种实现方式。 创建Demo 首先&#xff0c;创建一个简单的Demo&#xff1b; &#xff08…