C++中的继承——第二篇

一、继承与友元

友元关系不能够继承(就像父亲的朋友不一定是自己的朋友)

具体实现起来就是父类的友元可以访问父类的成员,但是不可以访问子类的成员

二、继承与静态成员

子类的静态成员变量本质上与父类的是同一份,存储在静态区中,所以可以继承

例如

复制代码
class Person
{
public:
    static int _count = 0
}

可以直接继承到子类

三、单继承与多继承

3.1单继承是什么?

一个子类只有一个直接父类,如:

复制代码
class Student : public Person
{}

3.2多继承

3.2.1定义

一个子类有两个及以上的直接父类,如:

复制代码
class Assistant : public Student,public Teacher
{}

3.2.2菱形继承中的数据冗余和二义性

用例子来说明:

如图,Student与Teacher都继承自Person,而Assistant又多继承了Student与Teacher,那么这时候Student与Teacher中属于Person的那一部分就会出现冗余,我们称之为数据冗余。

当我们运行下面一段代码的时候

复制代码
Assistant a;
a._name;

此时我们会发现在Assistant中有两份_name,一份属于Student,一份属于Teacher,因此运行时会因为不知访问那个而报错,我们称之为二义性。

3.2.3virtual:虚继承

按照之前分析,我们已经知道了数据冗余和二义性的存在,那么应该如何解决它呢?

为此,我们引入了virtual关键字来完成虚继承的概念,虚继承后,我们可以得到如下图的存储方式:

使用虚继承的方法也很简单,只需要在继承共有父类的时候加上virtual关键字:

复制代码
class Student: virtual public Person
{}
3.2.3补:复杂菱形继承时的位置

假如要完成如下图的复杂菱形继承

分析可知,在继承A的时候会出现数据冗余和二义性的问题,因此我们要在

A->B

A->C

这两个继承的时候使用virtual来修饰

3.3总结

在实际应用当中,我么并不推荐使用菱形继承,因为这会降低代码可读性(虽然iostream就是菱形继承),但是使用多继承是完全没问题的

四、继承和组合

4.1两者的本质都是:复用

4.1补:黑盒测试和白盒测试的概念

白盒测试:可见底层代码的实现,是对代码功能的实现过程进行测试,对技术要求高

黑盒测试:不可见代码的底层实现,直接对代码的功能进行测试,对技术要求低

4.2is-a关系与has-a关系(特指类之间的关系)

public继承是一种is-a关系,就是说每个派生类对象都是一个基类对象

组合是一种has-a关系,假设B组合了A,每个B对象中都有一个A对象,例如我们在vector类模板中在成员变量列表使用了迭代器类来作为成员变量

4.2补:在程序设计中,我们推荐"高内聚,低耦合"的代码形式

其中低耦合特指两个类之间关系,我们希望类与类之间关系不要太紧密。

4.3组合的好处

组合的原则是在类中少放公用,大多在保护中实现,仅仅向外展示功能接口,因此组合十分符合低耦合的形式

4.4继承与组合的对比

①继承允许根据基类的实现来定义派生类的实现,这种以生成派生类为目的的复用,我们称为白箱复用,但是因为白箱可视度高,所以基类的改变对派生类影响很大,耦合度比较高

②对象组合是继承之外的另一种复用方式,class Person中定义保护成员hand h1;

而hand是另外实现的一个类,这时两个类之间体现出了对象组合

在这个例子中,我们称hand类被Person类组合了,被组合的对象通常需要有良好的接口,这种复用风格成为黑箱复用,因为对象内部不可见,耦合度低

4.5is-a与has-a关系的应用场景

has-a关系时用对象组合,例如人体和手

is-a关系时用继承,例如植物和水果

当has-a与is-a都符合的时候,用组合,如list与queue

相关推荐
2601_966949654 小时前
如何根据研究的起止时间截取分钟级行情?Python 实战与 QuantDash 数据处理指南
开发语言·python·pandas·量化交易·1024程序员节·股票数据·quantdash
晨曦中的暮雨6 小时前
限流算法——固定窗口、滑动窗口、漏桶、令牌桶
java·开发语言·算法
喵了几个咪7 小时前
GoWind CMS 拆解:在 Go 里给 TipTap 搭一套 Yjs 协同后端
开发语言·后端·golang
程序员清风7 小时前
数据处理脚本工程化:日志、配置、命令行与测试
服务器·开发语言·数据库
文丑颜不良啊7 小时前
LeetCode876~900题目解析
java·leetcode
aloha_7898 小时前
Java 基础、集合、异常与 JUnit 5 速查
java·junit·sqlserver
知守观9 小时前
设计模式实战:从真实老项目中看标准模板方法与工厂的落地
java·spring·设计模式
2601_962885729 小时前
如何用 Python 把 K 线重采样成任意周期?
开发语言·python
独隅9 小时前
Claude API 实战教程:从入门到完整项目
android·java·数据库·claude·claude code
choumin9 小时前
C++中万能引用与std::forward的作用和用法
c++·万能引用·std forward