大家好
欢迎回来继续学习
C++语言程序设计
接下来
我们就来看一个
既有继承
又有组合的例子
那么通过这个跟踪调试呢
我们来观察一下
构造函数的调用顺序
在这个程序中呢
我们定义了一个派生类Derived
它继承了三个基类
Base2 Base1和Base3
都是公有继承
那么继承的顺序是先Base2
再Base1 再Base3
除此而外呢
它还有三个对象成员
分别是Base1的对象
Base2的对象
和Base3的对象
这是一个既有继承
又有组合的例子
那么我们关键来看
派生类的构造函数
怎么样给基类的构造函数
传递参数
怎么样在初始化列表中
给本类对象成员指定初始化参数
要运行一下主函数
看看在构造一个对象的时候
这些相关的构造函数
它们的调用次序是什么
我们先看这个派生类对象
在这里它给Base1类
传递了一个参数a
给Base2类传递了一个参数b
我们看看Base1类
确实它的构造函数需要一个参数
Base2的构造函数
也需要一个参数
但是Base3的构造函数
它不需要参数
所以在Derived构造函数中呢
当然就没有给Base3传递参数
同样呢
我们要给它的对象成员
指定初始化需要的参数
成员member2是Base2类型的
它需要一个参数
在这里我们给它指定了
b是给它的
成员member1它是Base1的对象
它的初始化需要一个参数
这里也给它了一个c
所以我们来看
在这个
Derived的构造函数的形参表中
列出了它需要传递给
基类构造函数的参数
需要用来初始化本类对象
本类这个对象成员的参数
都列在这儿了
然后在初始化列表中呢
分配一下
每个参数分别用来做什么
给谁
但是呢
这里列的次序
跟初始化的时候
执行构造函数的次序是无关的
这里并不是对构造函数来调用
只是一个初始化列表
列出哪些初始值给谁
而执行的次序是什么样的呢
应该是按照
首先按照基类自己
在这个继承的时候
排列的次序来执行
然后执行完了这些
再执行派生类
自己的对象成员的初始化
这个执行次序呢
按照这些成员定义时候
出现的次序
现在我们来运行这个主函数
验证一下
现在进到Derived构造函数里面
看看它接下来先调用
哪个构造函数
我们看到
进到了Base2的构造函数里面
这个跟这儿的书写次序
就不一样了
我们把Base1的初始化
写在最前面
但是呢在继承的时候
Base2排在前面
所以
先进到Base2的构造函数里面
回来以后
再跟踪一个函数进去
这回进到
Base1的构造函数里面了
这两个都是基类
所以基类的构造函数
是先被执行的
好 回来以后
接下来该执行什么了呢
我们来看看
进到Base3的构造函数中了
虽然这里没有给Base3
传递参数
因为Base3的构造函数
是不需要参数的
但是它也会按照继承时候
列出来的次序被调用的
首先
都是把基类的构造函数执行完
然后回来以后
接下来走到哪儿去呢
又进到
Base1的构造函数里面去了
这个时候是为了
初始化成员对象member1
那再次进到构造函数里面
进到谁里面去了呢
进到Base2的构造函数里面了
在这儿
这是为了初始化
成员对象member2
回来
现在就剩下成员对象mnmber3
没有初始化了
它也不需要参数
所以我们再跟踪一步
看
进到Base3的构造函数里面来了
这样三个成员对象
都被初始化完成了
那这个时候呢
由于Derived构造函数
它的函数体是空的
因此这个函数也就执行完了
回到主函数
现在这个对象已经构造完成了