【C++ | 继承】C++的继承详解 及 例子源码演示

😁博客主页😁:🚀https://blog.csdn.net/wkd_007🚀
🤑博客内容🤑:🍭嵌入式开发、Linux、C语言、C++、数据结构、音视频🍭
⏰发布时间⏰:

本文未经允许,不得转发!!!

目录

  • 🎄一、概述
  • 🎄二、继承的定义
  • 🎄三、派生类(子类)继承了什么
    • ✨3.1 派生类从基类继承了哪些东西
    • ✨3.2 继承的东西怎么使用
  • 🎄四、派生类对象的创建、销毁
  • 🎄五、
  • 🎄六、



在这里插入图片描述

🎄一、概述

继承的概念:

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

通过继承可以完成的一些工作:

  • 1、可以在己有类的基础上添加功能。 例如, 对于数组类, 可以添加数学运算。
  • 2、可以给类添加数据。 例如, 对于字符串类, 可以派生出一个类, 并添加指定字符串显示颜色的数据成员。
  • 3、可以修改类方法的行为。

按照继承权限区分,有公开继承、保护继承、私有继承三种方式。
按照继承的直接基类个数区分,有单继承、多重继承两种方式。


在这里插入图片描述

🎄二、继承的定义

通过继承 ( inheritance ) 联系在一起的类构成一种层次关系。通常在层次关系的根部有一个基类(base class),其他类则直接或间接地从基类继承而来,这些继承得到的类称为派生类(derived class)。基类负责定义在层次关系中所有类共同拥有的成员, 而每个派生类定义各自特有的成员

派生类必须通过使用**类派生列表(class derivation list)**明确指出它是从哪个(哪些)基类继承而来的。
类派生列表的形式是:首先是一个冒号,后面紧跟以逗号分隔的基类列表,其中每个基类前面可以有访问说明符。
在这里插入图片描述
访问说明符有三种:pulbic(公有继承)、protect(保护继承)、private(私有继承)。
类派生列表也可以有多个基类,如:class CDog : public CAnimal, public CFriend

下面用代码演示一下继承的过程:

class CAnimal{
public:CAnimal(){sprintf(m_name, "Ainmal");}void run(){cout << "my name is "<< m_name <<", Animal run" << endl;}
private:char m_name[64];
};class CDog : public CAnimal{};

is-a:我们这里使用的是 公有继承,它需要遵循is-a的关系,就是派生类 is a 基类,可以表示成派生类 是 基类,例如“狗 是 动物”。按照这个关系,我们不能在 动物苹果 之间使用公有继承。派生类对象也是一个基类对象,可以对基类对象执行的任何操作,也可以对派生类对象执行。


在这里插入图片描述

🎄三、派生类(子类)继承了什么

继承完之后,那么派生类继承了哪些东西?这些东西怎样使用呢?这个小节,我们来学习这两个问题的答案。

✨3.1 派生类从基类继承了哪些东西

派生类继承了基类的 数据成员 和 大部分的函数成员,而基类的 构造函数、析构函数、赋值运算符函数 不会被派生类所继承。

下面修改一下上面的代码,演示派生类继承了父类的数据成员。

// 22_Inheritance.cpp
// g++ 22_Inheritance.cpp 
#include <iostream>
#include <stdio.h>
#include <string.h>using namespace std;class CAnimal{enum{NAME_LEN=64};
public:CAnimal(){sprintf(m_name, "Ainmal");}void run(){cout << "my name is "<< m_name <<", Animal run" << endl;}
private:char m_name[NAME_LEN];
};class CDog : public CAnimal{
private:int m_hairColor;	// 毛发颜色
};int main ()
{CAnimal animal;cout << "sizeof(animal)=" << sizeof(animal) << endl;CDog dog;cout << "sizeof(dog)=" << sizeof(dog) << endl;return 0;
}

运行结果如下:

从结果来看,派生类CDog 比基类CAnimal 多了 4 个字节。这4个字节刚好是一个int型,也就是派生类多的 m_hairColor 成员。而成员函数也是被继承的,但成员函数并不会放在类对象的内存中,而是放在程序的代码段。打印类对象大小只会打印该对象的数据成员总和。

在这里插入图片描述

✨3.2 继承的东西怎么使用

派生类继承的成员并不是可以随意地访问,跟继承时使用的 访问说明符 以及该成员在 基类中的访问权限 有关。

按照访问说明符的不同,可以分为public继承、protected继承、private继承,它们从基类继承到的成员访问权限如下表:

类成员\继承方式public继承protected继承private继承
基类的public成员派生类的public成员派生类的protected成员派生类的private成员
基类的protected成员派生类的protected成员派生类的protected成员派生类的private成员
基类的private成员在派生类中不可见在派生类中不可见在派生类中不可见

从表格可以得出下面几个结论:
1、基类的私有成员,在派生类无法访问,只能通过基类的公有成员函数去访问。
2、基类的公有成员、保护成员,可以在派生类成员函数直接访问。
3、公有继承中,基类的公有成员、保护成员在派生类中也分别是公有、保护。
4、保护继承中,基类的公有成员、保护成员在派生类中都是保护的。
5、私有继承中,基类的公有成员、保护成员在派生类中都是私有的。

综上所述,派生类继承到的东西,并不是可以随意使用,而是按照上面表格和结论去使用。下面用代码演示怎样使用。代码使用了公有继承,基类的公有成员将成为派生类的公有成员;基类的私有部分也将成为派生类的一部分,但只能通过基类的公有和保护方法访问。

// 22_Inheritance1.cpp
// g++ 22_Inheritance1.cpp 
#include <iostream>
#include <stdio.h>
#include <string.h>using namespace std;class CAnimal{enum{NAME_LEN=64};
public:CAnimal(){sprintf(m_name, "Ainmal");}void run(){cout << "my name is "<< m_name <<", Animal run" << endl;}void SetName(const char *name)// 修改私有成员 m_name{int len = strlen(name) > NAME_LEN ? NAME_LEN : strlen(name);memset(m_name, 0, sizeof(m_name));strncpy(m_name, name, len);}const char *GetName(){return m_name;}
private:char m_name[NAME_LEN];
};class CDog : public CAnimal{
public:enum{HAIR_BLACK, HAIR_WHITE};CDog(){m_hairColor = HAIR_BLACK;//sprintf(m_name, "Dog"); // 报错,基类私有成员在派生类无法访问。}
private:int m_hairColor;	// 毛发颜色
};int main ()
{CAnimal animal;animal.run();CDog dog;dog.run();CDog dog1;dog1.SetName("dog1");dog1.run();return 0;
}

运行结果如下,代码演示了公有继承,派生类无法访问基类的m_name,但可以通过基类的公有函数SetName去修改m_name:
在这里插入图片描述


在这里插入图片描述

🎄四、派生类对象的创建、销毁

我们定义了一个派生类,大概率是需要用到这个派生类的对象的,那么派生类对象是怎样创建、销毁的呢?

创建派生类对象的几个要点:
1、派生类没有继承基类的构造函数。
2、创建派生类对象时,程序会先创建派生类对象的基类部分,所以,会先调用基类的构造函数,再调用派生类构造函数。
3、如果没有显式地调用基类构造函数,那么程序会自动调用基类的 无参构造函数 来创建派生类对象的基类部分。
4、如果要显式调用基类构造函数,为了保证先创建基类部分,需要在派生类构造函数的 成员初始化列表 去调用。
5、一般情况下,让基类构造函数初始化基类部分,派生类构造函数初始化派生类新增的数据成员。

派生类对象的销毁
派生类对象的销毁时,会先调用派生类的析构函数,再调用基类的析构函数。这个顺序与创建时相反。

🌰举例子:

// 22_Inheritance2.cpp
// g++ 22_Inheritance2.cpp 
#include <iostream>
#include <stdio.h>
#include <string.h>using namespace std;class CAnimal{enum{NAME_LEN=64};
public:CAnimal()						// 无参构造{sprintf(m_name, "Ainmal");cout << "Calling CAnimal(): this=" << this << endl;}CAnimal(char *name){int len = strlen(name) > NAME_LEN ? NAME_LEN : strlen(name);memset(m_name, 0, sizeof(m_name));strncpy(m_name, name, len);cout << "Calling CAnimal(char*): this=" << this << endl;}~CAnimal()						// 无参构造{cout << "Calling ~CAnimal(): this=" << this << endl;}void run(){cout << "my name is "<< m_name <<", Animal run" << endl;}
private:char m_name[NAME_LEN];
};class CDog : public CAnimal{
public:enum{HAIR_BLACK, HAIR_WHITE};CDog(){cout << "Calling CDog(): this=" << this << endl;m_hairColor = HAIR_BLACK;}CDog(int color, char* name) : CAnimal(name){cout << "Calling CDog(int, char*): this=" << this << endl;m_hairColor = color;}~CDog(){cout << "Calling ~CDog(): this=" << this << endl;}
private:int m_hairColor;	// 毛发颜色
};int main ()
{CDog dog;dog.run();cout << endl;CDog dog1(CDog::HAIR_BLACK, (char*)"dog1");dog1.run();cout << endl;return 0;
}

运行结果:
在这里插入图片描述


在这里插入图片描述

🎄五、

在这里插入图片描述

🎄六、

在这里插入图片描述
如果文章有帮助的话,点赞👍、收藏⭐,支持一波,谢谢 😁😁😁

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

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

相关文章

信用卡没逾期就万事大吉了吗?

6月28日&#xff0c;中国人民银行揭晓了《2024年第一季度支付体系概览》&#xff0c;数据显示&#xff0c;截至本季度末&#xff0c;信用卡及借贷合一卡的总量为7.6亿张&#xff0c;与上一季度相比&#xff0c;这一数字微降了0.85个百分点。同时&#xff0c;报告还指出&#xf…

AE的合成

目录 合成的概念 合成设置 预设 像素长宽比 分辨率​编辑 开始时间码和持续时间 背景颜色 合成的实战理解 在AE的操作界面中&#xff0c;当我们新建了一个项目之后&#xff0c;画面中最主要的位置显示的是新建合成 合成的概念 AE是一款专业特效合成软件&#xff0c;可…

【吊打面试官系列-MyBatis面试题】MyBatis 实现一对一有几种方式?具体怎么操作的?

大家好&#xff0c;我是锋哥。今天分享关于 【MyBatis 实现一对一有几种方式?具体怎么操作的&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; MyBatis 实现一对一有几种方式?具体怎么操作的&#xff1f; 有联合查询和嵌套查询,联合查询是几个表联合查询,只查询…

【记录】如何使用IDEA2023

前言&#xff1a; 记录IDEA2023的激活与安装 第一步&#xff1a;官网下载安装包&#xff1a; 下载地址&#xff1a;https://www.jetbrains.com/idea/download/other.html 这个最好选择2023版本&#xff0c;用着很nice。 安装步骤就不详解了&#xff0c;无脑下一步就可以了…

【并发编程】-3.锁的类型、CAS、UNSAFE、原子操作

锁的类型 可重入锁和不可重入锁 可重入锁&#xff1a;一个线程可以多次抢占同一个锁&#xff1b;Synchronized、ReentrantLock都是可重入锁&#xff0c;用Synchronized进行锁的可重入测试&#xff0c;在同一个线程中定义childMethod()和childMethod2()两个方法&#xff0c;在这…

使用Github Actions自建Docker镜像仓库

使用Github Actions自建Docker镜像仓库 背景使用Github Actions自建Docker镜像仓库fork项目[docker_image_sync](https://github.com/xqxyxchy/docker_image_sync)获取云厂商容器镜像服务信息配置github secrets运行github action配置需要同步的镜像同步后效果华为云配置 背景 …

VCS+Vivado联合仿真BUG

场景&#xff1a; 在vcsvivado联合仿真过程中&#xff0c;对vivado导出的shell脚本修改&#xff0c;修改某些source文件路径&#xff0c;vcs编译时会报Permission Denied。 问题描述 对shell脚本修改如下&#xff1a; 修改仅为注释掉某一行&#xff0c;下面变为source文件新…

昇思25天学习打卡营第07天|函数式自动微分

神经网络的训练主要使用反向传播算法&#xff0c;模型预测值&#xff08;logits&#xff09;与正确标签&#xff08;label&#xff09;送入损失函数&#xff08;loss function&#xff09;获得loss&#xff0c;然后进行反向传播计算&#xff0c;求得梯度&#xff08;gradients&…

hid-ft260驱动学习笔记 1 - 驱动模块注册与注销

目录 1. ft260_driver_init初始化 1.1 tty设备 1.1.1 申请tty驱动设备 1.1.2 初始化tty驱动程序 1.1.3 注册tty设备 1.2 hid设备 2. ft260_driver_exit注销模块 3. 调试 hid-ft260.c的最底部可以看到该驱动的注册与注销接口的申明。 module_init(ft260_driver_init); …

eclipse ide中文件编码的修改,解决中文乱码的问题。

1、先上一张图&#xff1a; 记得之前设置过&#xff0c;但是稍微一变&#xff0c;环境编码又到了ISO-8859-1了&#xff0c;然后就出现了乱码。 2、设置eclipse的编码&#xff1a; Preferences--General -- Content Types -- Text -- Java Properties File -- Default encoding…

使用myCobot280和OAK-D OpenCV DepthAI摄像头制作一个实时脸部跟踪的手机支架!

引言 由于YouTube和Netflix的出现&#xff0c;我们开始躺着看手机。然而&#xff0c;长时间用手拿着手机会让人感到疲劳。这次我们制作了一个可以在你眼前保持适当距离并调整位置的自动移动手机支架&#xff0c;让你无需用手拿着手机。请务必试试&#xff01; 准备工作 这次我们…

Vue3从入门到精通(三)

vue3插槽Slots 在 Vue3 中&#xff0c;插槽&#xff08;Slots&#xff09;的使用方式与 Vue2 中基本相同&#xff0c;但有一些细微的差异。以下是在 Vue3 中使用插槽的示例&#xff1a; // ChildComponent.vue <template><div><h2>Child Component</h2&…

昇思25天学习打卡营第08天|模型训练

模型训练 模型训练一般分为四个步骤&#xff1a; 构建数据集。定义神经网络模型。定义超参、损失函数及优化器。输入数据集进行训练与评估。 现在我们有了数据集和模型后&#xff0c;可以进行模型的训练与评估。 ps&#xff1a;这里的训练和Stable Diffusion中的训练是一样…

进程的概念

一.进程和程序的理解 首先抛出结论&#xff1a;进程是动态的&#xff0c;暂时存在于内存中&#xff0c;进程是程序的一次执行&#xff0c;而进程总是对应至少一个特定的程序。 程序是静态的&#xff0c;永久的存在于磁盘中。 程序是什么呢&#xff1f;程序其实就是存放在我们…

图像分类-数据驱动方法

K近邻算法&#xff08;K-Nearest Neighbors&#xff0c;简称KNN&#xff09; KNN算法通过比较新样本与训练集中的样本的距离&#xff0c;然后根据最近的K个邻居的投票结果来决定新样本的分类。 如图所示&#xff0c;K越大的边界会更加平滑&#xff0c;本质上是根据某一样本最近…

红薯小眼睛接口分析与Python脚本实现

文章目录 1. 写在前面2. 接口分析3. 算法脚本实现 【&#x1f3e0;作者主页】&#xff1a;吴秋霖 【&#x1f4bc;作者介绍】&#xff1a;擅长爬虫与JS加密逆向分析&#xff01;Python领域优质创作者、CSDN博客专家、阿里云博客专家、华为云享专家。一路走来长期坚守并致力于Py…

递归(三)—— 初识暴力递归之“字符串的全部子序列”

题目1 &#xff1a; 打印一个字符串的全部子序列 题目分析&#xff1a; 解法1&#xff1a;非递归方法 我们通过一个实例来理解题意&#xff0c;假设字符串str “abc”&#xff0c;那么它的子序列都有那些呢&#xff1f;" ", “a”&#xff0c; “b”&#xff0c;…

Vue的民族民俗文化分享平台-计算机毕业设计源码22552

基于Vue的民族民俗文化分享平台设计与实现 摘 要 本文介绍了一种基于Vue.js前端框架和Express后端框架的民族民俗文化分享平台的设计和实现。该平台旨在通过线上方式&#xff0c;促进民族民俗文化的传播与分享&#xff0c;增强公众对多元文化的了解和认同。 平台为普通用户提供…

前后端的导入、导出、模板下载等写法

导入&#xff0c;导出、模板下载等的前后端写法 文章目录 导入&#xff0c;导出、模板下载等的前后端写法一、导入实现1.1 后端的导入1.2 前端的导入 二、基础的模板下载2.1 后端的模板下载-若依基础版本2.2 前端的模板下载2.3 后端的模板下载 - 基于资源文件读取2.4 excel制作…

24西安电子科技大学马克思主义学院—考研录取情况

01、马克思主义学院各个方向 02、24马克思主义学院近三年复试分数线对比 PS&#xff1a;马院24年院线相对于23年院线增加15分&#xff0c;反映了大家对于马克思主义理论学习与研究的热情高涨&#xff0c;也彰显了学院在人才培养、学科建设及学术研究等方面的不断进步与成就。 6…