C++类的继承

目录

什么是继承?

父类与子类对象的赋值转换

继承中的作用域问题

子类的默认成员函数问题

如何使一个类不能被继承?

父类的友元和静态成员变量

多重继承与菱形继承

继承和组合


什么是继承?

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

继承类的格式:(class 子类名 : 继承方式 父类名)

如下面的形式

class Student : public Person
{}

基类,如Person 也叫做父类;派生类,如 Student 也叫子类

public为继承方式,还有 private,protected 继承,继承关系的原则就是父类在父类成员的权限和继承方式的权限中权限小的那一个!(如父类的 protected 成员在 public 继承后成了子类中的 protected 成员)

权限:public > protected > private 

子类无论怎样都不能访问父类的private。

父类与子类对象的赋值转换

class Person
{
public:void Print(){cout << _name << endl;}
protected:string _name; // 姓名
private:int _age = 18; // 年龄
};
class Student : public Person
{
protected:int _stunum; // 学号
};
int main()
{Student s;Person p = s;return 0;
}

子类可以赋值给父类,但父类不能赋值给子类!

因为子类肯定是 >= 父类的,所以子类给父类赋值是将子类中属于父类的那一部分拷贝过去。

上面的框中的代码也没有报错,原因是:C++中有个特殊规则,子类对象赋值给父类对象/父类指针/父类引用 的时候不会产生临时对象(父子类赋值兼容规则),所以上面的代码不用加 const 也可以通过运行。

继承中的作用域问题

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

子类的默认成员函数问题

子类的构造函数在调用之前,会先去调用父类的构造函数

当父类中没有默认构造的时候(即自己写了构造函数或拷贝构造),必须在子类的初始化列表中显示调用父类对应的构造函数。

析构函数必须先调子类的构析函数,再调用父类的构析函数。(析构函数不能先调用父类的构析,因为子类在构析时中可能还会访问父类中的某些成员)

构析函数的特殊处理:父子类的构析函数会构成隐藏

原因:由于多态原因,析构函数会被统一处理为 destructor()

如何使一个类不能被继承?

  • 1、当将一个类的构造函数设为私有后,这个类就变得无意义了
  • 2、C++11 新规定,若以 final 修饰一个类,则这个就类不能被继承了(并且继承时会强制报错)

父类的友元和静态成员变量

子类不能继承父类的友元关系(即父亲的朋友不是你的朋友)

如图,Display 是Person 的友元函数,Student 是 Person 的子类,因为它并没有继承 Display 和 Student 的友元关系,所以在Display 里不能访问 Student 里的 protected 和 private 的成员 _stuNum,即图片中的不可访问!

父类的静态成员变量和子类的关系:

子类继承了父类静态成员变量的使用权 

但将静态成员变量定义在子类中后,发现父类中也是可以使用的,所以静态成员变量在继承中是可以共享的。

多重继承与菱形继承

普通的继承叫单继承,一个子类只有一个直接父类。

多重继承:一个子类有多个直接父类。

语法格式:

class A:public B,public C,public D

多继承的关系看似没问题,但如果两个父类的直接父类是同一个类,就会导致很难处理的菱形继承

菱形继承如果不加处理会导致数据冗余和二义性问题

数据冗余:Person 类中的数据被建立了多份,比较费空间

二义性问题:

解决方法:虚拟继承

虚拟继承可以解决菱形继承的二义性和数据冗余的问题,但虚拟继承不能在其他地方使用!

语法格式:

在中间继承父类的时候加一个 virtual 即可。

虚拟继承的原理,比较复杂,在下一篇博客中解释。 

继承和组合

public继承是一种is-a的关系。也就是说每个派生类对象都是一个基类对象。
组合是一种has-a的关系。假设B组合了A,每个B对象中都有一个A对象,相当于定义在类 B 中加了一个 A 类型的成员变量。

那么使用继承还是组合,可以看这篇文章 :优先使用对象组合,而不是类继承

继承:

组合:

 

组合与继承的不同:B组合了A,但在B中不能调用A的 protected 成员和 private 成员;但如果 B继承了A,则B有时候是可以调用 A 的private 成员的。所以总的来说:继承的权限更大一些 

但继承的权限较大,父类内部的细节大部分对子类透明,这就导致了一个严重的问题:高耦合,会使代码维护起来更困难【白箱复用】。组合的优先就是,另一个类的内部细节被隐藏了,耦合度较低,可维护性较高【黑箱服用】。那么,从代码的可维护性来说,组合更好。

判断到底使用继承还是组合,主要看类与类的关系到底是什么当两个类的关系既符合继承又符合组合时,优先使用组合!

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

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

相关文章

数据库系统概论 ---知识点大全(期末复习版)

&#xff08;一&#xff09;绪论 数据(Data)&#xff1a;是数据库中存储的基本对象 数据的定义&#xff1a;描述事物的符号记录 数据的种类&#xff1a;文字、图形、图象、声音等 数据的特点&#xff1a;数据与其语义是不可分的 数据库(Database,简称DB)&#xff1a;是长期…

React 路由传参

引言 在上一篇中&#xff0c;我们学习了 React 中使用路由技术&#xff0c;以及如何使用 MyNavLink 去优化使用路由时的代码冗余的情况。 这一节我们继续上一篇 React 路由进行一些补充 1. Switch 解决相同路径问题 首先我们看一段这样的代码 <Route path"/home&q…

用栈和队列分别实现求解迷宫问题(c++,c)

求解迷宫问题&#xff1a;给定一个迷宫要求输出其路径。 给出的迷宫如下&#xff08;可自行更改&#xff09; 可用两种方法实现1.栈2.队列 用栈只能找到路但路不是最简的最简的要用队列实现 用栈实现&#xff08;解析都在代码里了&#xff09; c&#xff08;实现&#xff0…

Linux系统编程(六):进程(下)

参考引用 UNIX 环境高级编程 (第3版)嵌入式Linux C应用编程-正点原子 1. 进程与程序 1.1 main() 函数由谁调用&#xff1f; C 语言程序总是从 main 函数开始执行int main(void) int main(int argc, char *argv[]) // 如果需要向应用程序传参&#xff0c;则选择该种写法操作系…

应急响应中的溯源方法

在发现有入侵者后&#xff0c;快速由守转攻&#xff0c;进行精准地溯源反制&#xff0c;收集攻击路径和攻击者身份信息&#xff0c;勾勒出完整的攻击者画像。 对内溯源与对内溯源 对内溯源&#xff1a;确认攻击者的行为 &#xff0c;分析日志 数据包等&#xff1b; 对外溯源&…

20231223使用Rockchip原厂的Android11调通Firefly的AIO-3399J开发板上的AP6356S

20231223使用Rockchip原厂的Android11调通Firefly的AIO-3399J开发板上的AP6356S 2023/12/23 14:14 开发板&#xff1a;Firefly的AIO-3399J【RK3399】 SDK&#xff1a;rk3399-android-11-r20211216.tar.xz【Android11】 Android11.0.tar.bz2.aa【ToyBrick】 Android11.0.tar.bz2…

Druid源码阅读-DruidStatInterceptor实现

上次我们在druid-spring-boot-starter里面看到有一个DruidSpringAopConfiguration的配置类&#xff0c;然后引入了DruidStatInterceptor这样一个切面逻辑。今天我们就来看一下这个类的实现。 DruidStatInterceptor 这个类的包路径下入com.alibaba.druid.support.spring.stat。…

中国肺癌情形

写在前面 再看下中国肺癌的情形 综述 文章名期刊影响因子Non-small cell lung cancer in ChinaCancer Commun16.2 摘要 风险因子&#xff1a;吸烟史、家族史、放射暴露、空气污染、慢性肺病 晚期PD-1/PD-L1抑制剂单药使用或联合化疗药物作为标准治疗。局部肺癌晚期&#xf…

搭建react+ant design pro+umi 项目框架

一、 写本文的原因 我搭建reactantdumi这个框架的原始资料主要是来源于&#xff08;ReactUmi4从零快速搭建中后台系统保姆级记录教程&#xff08;一、项目创建及初始化&#xff09;&#xff09; 而我写这篇文章的本意就是用来记录我用搭建时候的步骤汇总。 二、 npm和node版…

PyQt5和Qt designer的详细安装教程

Qt designer界面和所有组件功能的详细介绍参考&#xff1a;https://blog.csdn.net/qq_43811536/article/details/135186862?spm1001.2014.3001.5501 目录 0. 写在前面1. Anaconda创建虚拟环境2. 安装PyQt5和Qt designer3. 测试安装成功 0. 写在前面 Qt Designer是Qt提供的一种…

小白入门之安装MYSQL

重生之我在大四学JAVA 第三章 安装MYSQL 把MySQL复制到要安装的路径下解压 到解压后的bin路径下复制路径 接着以“管理员”身份打开命令行(如下图所示) 注意&#xff1a;一定要是管理员身份&#xff0c;否则由于后续部分命令需要权限&#xff0c;出现错误&#xff01; 转到…

领像M100、L100系列打印机卡纸解决方法

故障现象: 联想打印软件或者机器电源键提示卡纸&#xff0c;具体故障报错如下&#xff1a; 软件内提示内部卡纸&#xff1a; 机器面板红灯常亮&#xff1a; 解决方案: 遇上述故障现象说明打印机内部卡纸&#xff0c;参考以下图文操作步骤解决。 1、机器断电并打开出纸口上盖&…