大家好
欢迎回来继续学习
C++语言程序设计
这一节呢
我们来学习类的组合
我们知道在制造业
多年来都一直使用
部件组装的生产方式
部件组装的生产方式呢
比一切手工从头做起
它的生产效率肯定是要高
产品呢
它的标准化 它的可靠性
也都更好
程序中我们是不是也可以
借用这种部件组装的思想呢
我们能不能用已经存在的这些类
去组装新的类呢
C++程序是可以这样的
C++语言支持类的组合
也就是说
我们在定义一个新类的时候
可以让它的类成员
是已有类的对象
也就是说
一些类的对象
可以作为另外一个类的部件
那么这个就是类的组合
类组合的基本概念就是
类中的成员
是另外其他类的对象
这样我们就可以在
已有的抽象基础上
实现更复杂的抽象
其实组合类的定义是很简单的
但是有一个问题
组合类的构造函数怎么设计呢
我们知道每个类的构造函数
都是负责自己本类成员初始化的
如果说我们用另外类的对象
作为新定义类的成员
那我们想一想
这个组合类有没有权利去访问
部件对象内部的私有成员呢
显然是没有权利访问的
因为一个类的私有成员
只有这个类内部的函数可以访问
类外任何地方是不可以访问的
而且部件类的设计者 开发者
跟组合类的设计者 开发者
可能不是一个人
甚至不是一个团队
那么这个时候
你怎么知道部件类
有哪些私有成员
你怎么能知道如何去写代码
初始化这些成员呢
显然是不行的
其实在制造业也是这样
我们买来部件 然后就组装
一般来讲
这个部件我们不会去拆开它
去修改它
而是直接拿来组装
程序中也是这样的道理
那么这些部件对象
它们的初始化怎么实现呢
这就要在写组合类
构造函数的时候
考虑到这个问题
要有组合类的构造函数
负责将部件对象初始化
所需要的初始化参数传递给它
然后呢
编译器会自动去调用部件类的
构造函数
来初始化这些部件对象
现在我们来看一下
这个组合类构造函数
它的语法形式应该是什么样的
我们来看
在这个组合类构造函数中
它的参数表中
就要多列一些参数
很可能需要多列一些参数
为什么呢
因为参数表中不仅要给出
初始化本类
基本类型数据成员的这些参数
还要考虑类中那些对象成员
他们怎么初始化
这些对象成员的初始化
会自动调用
它所属类的构造函数来完成
但是这些构造函数
它是需要参数的
这些参数有谁传给它呢
就由组合类的构造函数传给它
所以我们看
在这里初始化列表中
列出一个个的部件对象
在部件对象后面括号里面
要列出这些部件对象初始化
所需要的参数
现在我们来考虑
当有组合的时候
组合类的对象
它初始化的时候
这些构造次序
初始化次序是什么呢
现在我们就来看一看
组合类对象构造的时候
是按照什么样的次序来初始化的
首先
要对构造函数的初始化列表中
列出的成员
包括基本类型的成员
也包括对象成员进行初始化
那么类里面有那么多成员
都在初始化列表里列出来
谁先谁后呢
先初始化哪个呢
这个初始化次序
并不按照你初始化列表里的
列的次序来执行
而是按照成员在类体中
定义的次序来执行
也就是说
你的数据成员
谁定义在前
谁就初始化在前
谁定义在后
谁就后初始化
那么成员对象
它的构造函数调用的顺序
也是按照这些成员对象
在类体中声明的顺序来的
那么有的成员对象
可能你在初始化列表中
没有给列出来
那它怎么初始化呢
如果你在初始化列表中
没有列出某些成员对象
那这些成员对象初始化的时候
就要调用它自己所属类的
默认构造函数
也就是不需要形参的构造函数
来进行初始化
当整个初始化列表
都处理完了之后
才会执行构造函数的函数体
那么现在
我们来考虑这样一个问题
如果作为部件对象的
它的所属类
没有定义默认构造函数
那你在初始化
这个组合类对象的时候
是不是就必须得给这个部件
对象的初始化传递参数啊
如果部件对象没有默认构造函数
也就是说
它的构造必须要参数
那组合类它的构造函数
就必须给它传参数
这个时候如果你不给它传参数
编译的时候编译器就会报错
说找不到它的默认构造函数
所以呢返回来想
如果你写一个类
希望它非常通用
希望它经常能够被重用
能够用在很多场合 很多地方
那你就要记住
不管你给它写了多少个构造函数
记住 再多写一个
不要参数的默认构造函数
因为当这个类的对象
被用作其他类的部件成员的时候
可能那个组合类
根本就不写构造函数
就用默认构造函数
有没有这个可能
当然有这个可能
如果组合类根本就不写构造函数
那它还能给部件对象
传什么参数吗
肯定就不会传参数了
这个时候就需要它的部件对象
一定得有默认构造函数
当然了 我们写组合类的时候
也会去参照它部件对象
所属类的相关的接口说明
去看看它是不是需要传参数
这些两方面都兼顾到
我们才能够顺利地去重用
已经定义好的类