C++继承与构造函数调用分析
·
#include<iostream>
using namespace std;
class Base1{
public:
Base1(int i){cout<<i<<endl;}
};
class Base2{
public:
Base2(int i){cout<<i<<endl;}
};
class Base3{
public:
Base3(){cout<<"*"<<endl;}
};
class Derived:public Base2,public Base1,public Base3{
public:
Derived(int a,int b,int c,int d):Base1(a),Base2(b),m1(a),m2(b){}
private:
Base1 m1;
Base2 m2;
Base3 m3;
};
int main(){
Derived d{1,2,3,4};
return 0;
}
我们来逐步分析这段代码的执行过程和输出结果。
代码结构
- 定义了三个基类:
Base1、Base2和Base3,每个类都有一个构造函数。 - 定义了一个派生类
Derived,它公有继承自Base2、Base1和Base3(注意继承顺序)。 Derived类包含三个私有成员对象:m1(Base1类型)、m2(Base2类型)和m3(Base3类型)。Derived的构造函数接受四个参数(a, b, c, d),并在初始化列表中初始化基类和成员对象。- 在
main函数中,创建了一个Derived对象d,传入参数{1,2,3,4}。
构造函数调用顺序
当创建Derived对象时,构造函数调用顺序如下:
- 基类构造函数:按照继承声明的顺序(
Base2、Base1、Base3)调用。- 首先调用
Base2的构造函数(传入参数b,即2),输出2。 - 然后调用
Base1的构造函数(传入参数a,即1),输出1。 - 最后调用
Base3的构造函数(无参数),输出*。
- 首先调用
- 成员对象构造函数:按照在类中声明的顺序(
m1、m2、m3)调用。- 首先构造
m1(Base1类型,传入参数a即1),输出1。 - 然后构造
m2(Base2类型,传入参数b即2),输出2。 - 最后构造
m3(Base3类型,无参数),输出*。
- 首先构造
注意:虽然Derived的初始化列表中写了Base1(a), Base2(b),但基类的构造顺序只取决于继承顺序(Base2先于Base1),而不是初始化列表中的顺序。成员对象的构造顺序取决于它们在类中的声明顺序(m1、m2、m3),而不是初始化列表中的顺序。
参数传递
在main中创建Derived对象时:
Derived d{1,2,3,4};
参数分别对应:
a=1,b=2,c=3,d=4(但c和d在构造函数中未使用)。
输出结果
根据以上分析,输出顺序为:
- 基类
Base2构造:输出2 - 基类
Base1构造:输出1 - 基类
Base3构造:输出* - 成员
m1(Base1)构造:输出1 - 成员
m2(Base2)构造:输出2 - 成员
m3(Base3)构造:输出*
因此,最终输出为:2 1 * 1 2 *
完整输出
2
1
*
1
2
*
总结
代码输出为:
2
1
*
1
2
*
更多推荐
所有评论(0)