C++ 类的继承与派生

1.继承关系举例

交通工具的分类如下图所示:
在这里插入图片描述
这个分类树反映了交通工具的派生关系,最高层是抽象程度最高的,是最具有普遍和一般意义的概念,下层具有了上层的特性,同时加入了自己的新特征,而最下层是最为具体的。这个层次结构中,由上到下,是一个具体化、特殊化的过程;由下到上,是一个抽象化的过程。上下层之间的关系就可以看作是基类与派生类的关系。

所谓继承就是从先辈处得到属性和行为特征。类的继承,就是新的类从已有类那里得到已有的特性。 从另一个角度来看这个问题,从已有类产生新类的过程就是类的派生。 类的继承与派生机制允许程序员在保持原有类特性的基础上,进行更具体、更详细的修改和扩充。由原有的类产生新类时,新类便包含了原有类的特征,同时也可以加入自己所特有的新特性。原有的类称为基类或父类产生的新类称为派生类或子类。 派生类同样也可以作为基类派生新的类,这样就形成了类的层次结构。类的派生实际上是一种演化、发展过程,即通过扩展、更改和特殊化,从一个已知类出发建立一个新类。通过类的派生可以建立具有共同关键特征的对象家族,从而实现代码的重用,这种继承和派生的机制对于已有程序的发展和改进非常有利。

2.派生类的定义

(1)派生类的一般定义语法

在C++中,派生类的一般定义语法为:

class 派生类名::继承方式 基类名1,继承方式 基类名2,...,继承方式 基类名n
{派生类成员声明;
};

例如,假设基类B1和B2是已经定义的类,下面的语句定义了一个名为D的派生类,该类从基类B1和B2派生而来:

class D::public B1,private B2
{public:D();~D();
};

定义中的“基类名”(如B1和B2)是已有的类的名称,“派生类名”是继承原有类的特性而生成的新类的名称(如D)。

(2)多继承和单继承

一个派生类,可以同时有多个基类,这种情况称为多继承,这时的派生类同时得到了多个已有类的特征。上述例子就是一个多继承实例。一个派生类只有一个直接基类的情况,称为单继承。单继承可以看作是多继承的一个最简单的特例,多继承可以看作是多个单继承的组合,它们之间的很多特性是相同的。两种继承的UML表示如图所示:

在这里插入图片描述
(3)直接基类和间接基类

在派生过程中,派生出来的新类也同样可以作为基类再继续派生新的类,此外,一个基类可以同时派生处多个派生类,也就是说,一个类从父类继承来的特征也可以被其他新的类所继承,一个父类的特征,可以同时被多个子类继承。这样,就形成了一个相互关联的类的家族,有时也称作类族。在类族中,直接参与派生出某类的基类称为直接基类基类的基类甚至更高层的基类称为间接基类。比如由“交通工具”类派生出“汽车”类,“汽车”类又派生出“卡车”类,则“汽车”类是“卡车”类的直接基类,“交通工具”类是“汽车”类的直接基类,而“交通工具”类是“卡车”类的间接基类。

(4)继承方式
在派生类的定义中,除了要指定基类外,还需要指定继承方式。继承方式规定了如何访问从基类继承的成员。。在派生类的定义语句中,每一个“继承方式”,只限定紧随其后的基类。继承方式关键字为:public,protected和private,分别表示公有继承。保护继承和私有继承。如果不显式地给出继承方式关键字,系统的默认值就认为是私有继承(private)。类的继承方式指定了派生类成员以及类外对象对于从基类继承来的成员的访问权限。在下面这个例子中:

class D::public B1,private B2
{public:D();~D();
};

对B1是公有继承,对B2是私有继承,同时声明了派生类自己新的构造函数和析构函数。

(5)派生类成员

派生类成员是指除了从基类继承来的所有成员之外,新增加的数据和函数成员。 这些新增的成员,正是派生类不同于基类的关键所在,是派生类对基类的发展。当重用和扩充已有的代码时,就是通过在派生类中新增成员来添加新的属性和功能。

3.派生类生成过程

在C++程序设计中,进行派生类的定义之后,给出该类的成员函数的实现,整个类就算完成了,可以由它来生成对象进行实际问题的处理。

派生新类,实际经历了3个步骤:吸收基类成员,改造基类成员、添加基类成员。

面向对象的继承和派生机制,其最主要目的是实现代码的重用与扩充。因此吸收基类成员就是一个重用的过程,而对基类成员进行调整、改造以及添加新成员就是原有代码的扩充过程,二者是相辅相成的。

基类A和派生类B的定义如下:

class A
{
private:string i;double b;static int t;
protected:A();void r();void e()const;
public:const string &gi()const{}double gb()const{}static double gt(){}void show()const;
};class B :public A
{
private:A a;double c;double r;double q;double gd()const;
public:B();double gc()const;double gr()const;double gq()const;double ga();void de();void wi();void se();void show()const;
};

(1)吸收基类成员
在C++继承中,第一步是将基类的成员全盘接收,这样,派生类实际上就包含了它的全部基类中除构造函数和析构函数之外的所有成员。**在派生过程中构造函数和析构函数都不被继承。**在这里,派生类B继承了基类A中除构造函数和析构函数之外的所有非静态成员:i,b,r函数,e函数,gi函数,gb函数,show函数。经过派生过程,这些成员便存在于派生类之中。

(2)改造基类成员
对基类成员的改造包括两个方面:一个是基类成员的访问控制问题,主要依靠派生类定义时的继承方式来控制。另一个是对基类数据或函数成员的覆盖或隐藏,隐藏就是简单地在派生类中声明一个和基类数据或函数同名的成员,例如上例中的show函数。如果派生类声明了一个和某基类成员同名的新成员(如果是函数成员,则参数表也要相同,参数不同的情况属于重载),派生的新成员就隐藏了外层同名成员。 这时派生类中或者通过派生类的对象,直接使用成员名就只能访问到派生类中声明的同名成员,这称为同名隐藏。在上例中,派生类B中的show函数就隐藏了基类A中的同名函数。

(3)添加新的成员
派生类新成员的加入是继承与派生的核心,是保证派生类在功能上有所发展的关键。可以根据实际情况的需要,给派生类添加适当的数据和函数成员,来实现必要的新增功能。在上例,派生类B中就添加了数据成员a,c,r,q。

由于在派生过程中,基类的构造函数和析构函数不能被继承,因此要实现一些特别的初始化和扫尾清理工作,就需要在派生类中加入新的构造函数和析构函数。例如派生类B中的构造函数B()。

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

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

相关文章

[CKA]考试之PersistentVolumeClaims

由于最新的CKA考试改版,不允许存储书签,本博客致力怎么一步步从官网把答案找到,如何修改把题做对,下面开始我们的 CKA之旅 题目为: Task 创建一个名字为pv-volume的pvc,指定storageClass为csi-hostpath-…

HTML中元素和标签有什么区别?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐ 标签(Tag)⭐元素(Element)⭐ 写在最后 ⭐ 专栏简介 前端入门之旅:探索Web开发的奇妙世界 记得点击上方或者右侧链接订阅本专栏哦 几何带你启航前端之旅 欢迎来到前端入门之旅&a…

Leetcode-每日一题【剑指 Offer 17. 打印从1到最大的n位数】

题目 输入数字 n,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3,则打印出 1、2、3 一直到最大的 3 位数 999。 示例 1: 输入: n 1输出: [1,2,3,4,5,6,7,8,9] 说明: 用返回一个整数列表来代替打印 n 为正整数 解题思路 前置知识 M…

kubernetes基于helm部署gitlab

kubernetes基于helm部署gitlab 这篇博文介绍如何在 Kubernetes 中使用helm部署 GitLab。 先决条件 已运行的 Kubernetes 集群负载均衡器,为ingress-nginx控制器提供EXTERNAL-IP,本示例使用metallb默认存储类,为gitlab pods提供持久化存储&…

将word每页页眉单独设置

在进行论文排版的时候,总是会出现页眉的页码设置问题,比如出现奇数或偶数页码一致,尝试将前面页码改掉,后面再修改前面也进行了变动,将每页页眉单独设置: (1)在第一页的最后一行输入…

OPENCV C++(四)形态学操作+连通域统计

形态学操作 先得到一个卷积核 Mat kernel getStructuringElement(MORPH_RECT,Size(5,5)); 第一个是形状 第二个是卷积核大小 依次为腐蚀 膨胀 开运算 闭运算 Mat erodemat,dilatemat,openmat,closemat;morphologyEx(result1, erodemat, MORPH_ERODE, kernel);morphologyEx…

智能指针shared_ptr:自定义删除器

重点&#xff1a; 1.普通指针转化成智能指针。 2.智能指针创建的时候&#xff0c;第二个参数是自定义删除器&#xff0c;默认情况下&#xff0c;shared_ptr调用delete()函数。 class A { public:void Get() { cout << b << endl; }; private:int b{ 10 }; };clas…

Pandas

系列文章目录 第一章 python数据挖掘基础环境安装和使用 第二章 Matplotlib 第三章 Numpy 文章目录 系列文章目录一、介绍1.1 为什么用Pandas&#xff1f;1.2 核心数据结构1.3 DataFrame1.3.1 结构1.3.2 常用属性1.3.3 常用方法1.3.4 DataFrame索引的设置修改行列索引值重设索…

git仓库与本地暂存区的同步问题

向下同步 对于远程仓库的项目&#xff0c;初始化一个配置文件&#xff0c;配置远程仓库及相关信息&#xff0c;赋值远程仓库的地址&#xff0c;使用git pull命令即可拉取仓库代码。 git pull [remote_addr] 该部分完成向下同步 向上同步 向上同步时会遇到很多的问题&#xf…

《手把手教你》系列基础篇之4-python+ selenium自动化测试-xpath使用(详细教程)

1. 简介 俗话说&#xff1a;磨刀不误砍柴工&#xff0c;因此在我们要开始写自动化脚本之前&#xff0c;我们先来学习和了解几个基本概念&#xff0c;在完全掌握了这几个概念之后&#xff0c;有助于我们快速上手&#xff0c;如何去编写自动化测试脚本。 元素&#xff0c;在这个…

【问题随记】

ubuntu 14.04源更新(sources.list) deb http://mirrors.aliyun.com/ubuntu/ trusty main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ trusty-security main restricted universe multiverse deb http://mirrors.aliyun.com/ubuntu/ trusty-update…

clickhouse查询缓存

为了实现最佳性能&#xff0c;数据库需要优化其内部数据存储和处理管道的每一步。但是数据库执行的最好的工作是根本没有完成的工作&#xff01;缓存是一种特别流行的技术&#xff0c;它通过存储早期计算的结果或远程数据来避免不必要的工作&#xff0c;而访问这些数据的成本往…

软件测试需求分析的常用方法

软件测试需求分析时&#xff0c;应要求产品人员对需求进行讲解&#xff0c;并使用相对应的方法进行科学分析&#xff0c;否则无法保障软件测试的完整性和科学性&#xff0c;从而造成在项目中后期Bug频出、风险增大等问题。 而常用的测试需求分析的方法&#xff1a; 1、功能分解…

解决 MySQL 删除数据后,ID 自增不连续问题

修复前 除了部分数据&#xff0c;导致后续新增的数据&#xff0c;ID 自增不连续 解决方案 执行下方 SQL 语句即可修复此问题&#xff0c;mbs_order为需要修复的表名 SET i0; UPDATE mbs_order SET id(i:i1); ALTER TABLE mbs_order AUTO_INCREMENT0;

进程与线程、线程创建、线程周期、多线程安全和线程池(ThreadPoolExecutor)

目录 进程与线程线程和进程的区别是什么&#xff1f;线程分两种&#xff1a;用户线程和守护线程线程创建四种方式run()和start()方法区别&#xff1a;为什么调用 start() 方法时会执行 run() 方法&#xff0c;为什么不能直接调用 run() 方法&#xff1f;Runnable接口和Callable…

该选择WPF 还是 Winform?

WPF和WinForms都是.NET平台下的桌面应用程序开发框架&#xff0c;它们各有特点&#xff0c;适用于不同的场景和需求。下面是对WPF和WinForms的一些比较和优劣势&#xff1a;WPF&#xff08;Windows Presentation Foundation&#xff09;&#xff1a;WPF具有强大的图形渲染能力&…

刷题笔记 day7

力扣 209 长度最小的子数组 解法&#xff1a;滑动指针&#xff08;对同向双指针区间内的数据处理&#xff09; 1&#xff09;先初始化 两个指针 left &#xff0c;right。 2&#xff09;右移指针right的同时使用sum记录指针right处的值&#xff0c;并判断sum的值是否满足要求&…

iOS--Runloop

Runloop概述 一般来说&#xff0c;一个线程一次只能执行一个任务&#xff0c;执行完成后线程就会退出。就比如之前学OC时使用的命令行程序&#xff0c;执行完程序就结束了。 而runloop目的就是使线程在执行完一次代码之后不会结束程序&#xff0c;而是使该线程处于一种休眠的状…

更新页面无法回显

需求与问题&#xff1a; 在菜品管理开发中&#xff0c;我需要修改菜品&#xff0c;第一步是回显页面&#xff0c;但在我再三确认代码无误的情况下依旧无法回显内容 问题发现与解决&#xff1a; 经过排查&#xff0c;我发现我的DishDTO内容如下&#xff1a; Data public clas…

【C++】类和对象-多态

1.多态的基本语法 代码 #include <iostream> using namespace std; /******************************************/ class Animal { public://speak函数就是虚函数//函数前面加上virtual关键字&#xff0c;变成虚函数&#xff0c;//那么编译器在编译的时候就不能确定函数…