1.继承的概念和定义

1.1继承的概念

继承机制是面向对象程序设计使代码可以复用的最重要的手段,它允许我们在保持原有类特性的基础上进行扩展,增加方法(成员函数)和属性(成员变量),这一产生新的类,称为子类。继承呈现了面向对象程序设计的结构

以下面这两个类举例

我们很容易注意到,这两个类有重复部分,这时我们就可以把公共的信息提取出来,放到person类里面,就不需要去重复定义了

1.2继承定义

1.2.1定义格式

下面我们看到Person是父类,也称作基类。Student是子类,也称作派生类

1.父类的private成员在子类中无论以什么方式继承都是不可见的,不可见的意思是,被继承了,但是不能通过任何方式访问

2.父类private成员在子类中是不能被访问,如果父类成员不想在类外直接被访问,但需要在子类中能被访问就定义为protected

3.父类其他成员在子类的访问方式 == Min(成员在父类的访问限定符,继承方式)

4.使用class的默认继承方式是private,使用struct的默认继承方式的public

5.实际运用时一般都是使用public继承,很少使用protected和private

1.3继承类模板

2.父类和子类赋值兼容转换

1.public继承(在公有继承的前提下)的子类对象可以赋值给父类的对象/父类的指针/父类的引用(赋值只能赋值从父类继承的部分,不能赋值子类独有的部分)

2.父类对象不能赋值给子类对象

3.父类的指针或者引用可以通过强制类型转换赋值给子类的指针或引用,但是必须是父类的指针是指向子类对象时才是安全的

从这里就能看出,继承下的变量是同一类型,无需进行类型转换,而下面的那个,必须进行类型转换才能绑定引用(引用必须绑定在一个内存中真实存在的数据,就是无需进行类型转换之类的操作,立马就有的数据)

3.1继承中的作用域

3.1隐藏规则:

1.在继承体系中父类和子类都有独立的作用域

2.子类和父类中有同名成员,子类成员将屏蔽父类对同名成员的直接访问,这种情况叫做隐藏

(在子类成员函数中,可以使用父类::父类成员显示访问)

3.需要注意的是如果是成员函数的隐藏,只需要函数名相同就构成隐藏

4.注意在实际中继承体系里面最好不要定义同名的成员

4.子类的默认成员函数

4.1  4个常见的默认成员函数

默认成员构造函数的意思就是我们不写会自动生成一个

1.子类的构造函数必须调用父类的构造函数初始化父类的那一部分成员,如果父类没有默认构造函数,则必须在子类构造函数的初始化阶段显示调用

必须这样显示调用

2.子类的拷贝构造函数必须调用父类的拷贝构造完成父类的拷贝初始化

3.子类的operator=必须要调用父类的operator=完成父类的复制,需要注意的是子类的operator=隐藏了父类的operator=,所以显示调用父类的operator=,需要指定父类作用域

4.2实现一个不能被继承的类

方法一:父类的构造私有,子类的构成必须调用父类的构造函数,但是父类的构造函数私有化后,子类看不见就不能调用了,那么子类就无法实例化出对象

方法二:C++11新增关键字final,final修改父类,子类就不能继承了

5.继承与友元

友元关系不能继承,也就是父类的友元不能访问子类的私有成员

补充:友元函数

. 三种形式
友元全局函数:授权一个普通的全局函数来访问类的内部数据。
友元类:授权整个类,使其所有成员函数都能访问当前类的私有成员(常用于紧密耦合的类,如容器与迭代器)。
友元成员函数:只授权另一个类中的某一个特定成员函数。
. 三大铁律
单向性:A 是 B 的友元,不代表 B 是 A 的友元。
不传递:A 是 B 的友元,B 是 C 的友元,不代表 A 能访问 C。
不继承:基类的友元,不会自动成为派生类的友元。

6.继承与静态成员

父类定义了static静态成员,则整个继承体系里面只有一个这样的成员,无论派生出多少个子类,都只有一个static成员实例

7.多继承以及菱形继承问题

单继承:一个子类只有一个直接父类时称这个继承关系为单继承

多继承:一个子类有两个或以上直接父类时,称这个继承关系为多继承,多几次对象在内存中的模型是,先几次父类在前面,后面几次的父类在后面,子类成员放到最后面

菱形继承:菱形继承是多继承的一种特殊情况,会出现数据冗余和多义性的问题

7.2虚继承(这个一定要给两份及以上)

使用虚继承就是virtual就可以解决这个问题,在内存中值保留一份共享的基类成员,让基类成员不再报错,解决了二义性的问题,还有一点在普通继承中,每个类负责调用自己直接父类的构造函数。但在虚继承中,为了保证基类只被初始化一次,虚基类的构造函数必须由继承体系中最底层的那个类(最派生类)直接调用和初始化

注意:这个不能随便乱用,虚拟继承付出了不小的代价,在初始化方面容易错乱,很容易出错

8.继承和组合

1.public继承是一种is-a的关系,也就是说每一个子类对象都是一个父类对象

2.组合是一种has-a的关系,假设B组合了A,每一个B对象中都有一个A对象

3.继承允许你根据父类的实现来定义子类的实现,这种通过生成子类的复用通常为称为白箱复用,

在继承方式中,父类内部的细节对子类可见。继承一定程度破坏了父类的封装,父类的改变,对子类有很大的影响。子类和父类之间依赖关系强,耦合度高

对象组合是类继承之外另外一种复用选择,新的更复杂的功能可以通过组装或者组合对象来获得。对象组合要求被组合的对象具有良好定义的接口,这种复用被称为黑箱复用,因为对象内部细节是不可见的,所以组合之间没有很强的依赖关系,耦合度低,优先使用对象组合有利于保持每一个类的封装

耦合度:程序之间互相依赖和连接的紧密度

高内聚:让模块内部的各个元素紧密相关,专注于完成单一、明确的功能。

低耦合,高内聚

以上面为例,继承中栈是一种特殊的链表,组合中,栈里面有一个链表

更多推荐