四十三、继承的概念和意义
1、思考:类之间是否存在直接的关联关系?
2、生活中的例子
- 组合关系:整体与部分的关系
3、实例分析:组合关系的描述
4、类之间的组合关系
- 组合关系的特点
- 将其它类的对象作为当前类的成员使用
- 当前类的对象与成员对象的生命期相同
- 成员对象在用法上与普通对象完全一致
5、生活中的例子
- 继承关系:父子关系
6、惊艳的继承
- 面向对象中的继承指类之间的父子关系
- 子类拥有父类的所有属性和行为
- 子类就是一种特殊的父类
- 子类对象可以当作父类对象使用
- 子类中可以添加父类没有的方法和属性
- C++中通过下面的方式描述继承关系
7、编程实验:继承初体验
8、惊艳的继承
- 重要规则:
- 子类就是一个特殊的父类
- 子类对象可以直接初始化父类对象
- 子类对象可以直接赋值给父类对象
9、继承的意义
继承是C++中代码复用的重要手段。通过继承,可以获得父类的所有功能,并且可以在子类中重写已有功能,或者添加新功能。
10、编程实验:继承的强化练习
11、小结
- 继承是面向对象中类之间的一种关系
- 子类拥有父类的所有属性和行为
- 子类对象可以当作父类对象使用
- 子类中可以添加父类没有的方法和属性
- 继承是面向对象中代码复用的重要手段
四十四、继承中的访问级别
1、值得思考的问题
子类是否可以直接访问父类的私有成员?
2、思考过程
3、编程实验:继承中的访问级别
4、继承中的访问级别
- 面向对象中的访问级别不只是public和private
- 可以定义protected访问级别
- 关键字protected的意义
- 修饰的成员不能被外界直接访问
- 修饰的成员可以被子类直接访问
5、编程实验:protected初体验
6、思考:为什么面向对象中需要protected?
7、定义类时访问级别的选择
8、组合与继承的综合实例
Point和Line继承Object,Line由Point组合
9、编程实验:综合实例
10、小结
- 面向对象中的访问级别不只是public 和private
- protected修饰的成员不能被外界所访问
- protected使得子类能够访问父类的成员
- protected关键字是为了继承而专门设计的
- 没有protected就无法完成真正意义上的代码复用
四十五、不同的继承方式
1、被忽视的细节
- 冒号( : )表示继承关系,Parent表示被继承的类,public的意义是什么?
2、有趣的问题
- 是否可以将继承语句中的public换成protected或者private ?如果可以,与public继承有什么区别?
3、编程实验:有趣的尝试
4、不同的继承方式
- C++中支持三种不同的继承方式
- public继承
- 父类成员在子类中保持原有访问级别
- private继承
- 父类成员在子类中变为私有成员
- protected继承
- 父类中的公有成员变为保护成员,其它成员保持不变
- public继承
继承成员的访问属性
= Max {继承方式,父类成员访问属性}
C++中的默认继承方式为private !
5、编程实验:继承与访问级别深度实践
6、遗憾的事实
- 一般而言,C++工程项目中只使用public继承
- C++的派生语言只支持一种继承方式(public继承)
- protected和private继承带来的复杂性远大于实用性
7、编程实验:C++派生语言初探 - d语言 / c# / java
8、小结
- C++中支持3种不同的继承方式
- 继承方式直接影响父类成员在子类中的访问属性
- 一般而言,工程中只使用public的继承方式
- C++的派生语言中只支持public继承方式
四十六、继承中的构造与析构
1、思考
如何初始化父类成员?
父类构造函数和子类构造函数有什么关系?
2、子类对象的构造
- 子类中可以定义构造函数
- 子类构造函数
- 必须对继承而来的成员进行初始化
- 直接通过初始化列表或者赋值的方式进行初始
- 调用父类构造函数进行初始化
- 必须对继承而来的成员进行初始化
- 父类构造函数在子类中的调用方式
- 默认调用
- 适用于无参构造函数和使用默认参数的构造函数
- 显示调用
- 通过初始化列表进行调用
- 适用于所有父类构造函数
- 默认调用
- 父类构造函数的调用
3、编程实验:子类的构造初探
4、子类对象的构造
- 构造规则
- 子类对象在创建时会首先调用父类的构造函数
- 先执行父类构造函数再执行子类的构造函数
- 父类构造函数可以被隐式调用或者显示调用
- 对象创建时构造函数的调用顺序
- 调用父类的构造函数
- 调用成员变量的构造函数
- 调用类自身的构造函数
- 口诀心法:先父母,后客人,再自己。
5、编程实验:子类构造深度解析
6、子类对象的析构
- 析构函数的调用顺序与构造函数相反
- 执行自身的析构函数
- 执行成员变量的析构函数
- 执行父类的析构函数
7、编程实验:对象的析构
8、小结
- 子类对象在创建时需要调用父类构造函数进行初始化
- 先执行父类构造函数然后执行成员的构造函数
- 父类构造函数显示调用需要在初始化列表中进行
- 子类对象在销毁时需要调用父类析构函数进行清理
- 析构顺序与构造顺序对称相反