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

相关推荐
上单带刀不带妹6 分钟前
手写 Vue 中虚拟 DOM 到真实 DOM 的完整过程
开发语言·前端·javascript·vue.js·前端框架
都叫我大帅哥26 分钟前
🌊 Redis Stream深度探险:从秒杀系统到面试通关
java·redis
都叫我大帅哥27 分钟前
Redis持久化全解析:从健忘症患者到记忆大师的逆袭
java·redis
程序猿阿越1 小时前
Kafka源码(一)Controller选举与创建Topic
java·后端·源码
-凌凌漆-1 小时前
【Qt】QStringLiteral 介绍
开发语言·qt
程序员爱钓鱼1 小时前
Go语言项目工程化 — 常见开发工具与 CI/CD 支持
开发语言·后端·golang·gin
程序无bug1 小时前
Spring6 当中 Bean 的生命周期的详细解析:有五步,有七步,有十步
java
二川bro1 小时前
飞算智造JavaAI:智能编程革命——AI重构Java开发新范式
java·人工智能·重构
Q_970956391 小时前
java+vue+SpringBoo校园失物招领网站(程序+数据库+报告+部署教程+答辩指导)
java·数据库·vue.js