#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;
    }

我们来逐步分析这段代码的执行过程和输出结果。

代码结构

  1. 定义了三个基类:Base1Base2Base3,每个类都有一个构造函数。
  2. 定义了一个派生类 Derived,它公有继承自 Base2Base1Base3(注意继承顺序)。
  3. Derived 类包含三个私有成员对象:m1Base1类型)、m2Base2类型)和m3Base3类型)。
  4. Derived 的构造函数接受四个参数(a, b, c, d),并在初始化列表中初始化基类和成员对象。
  5. main函数中,创建了一个Derived对象d,传入参数{1,2,3,4}

构造函数调用顺序

当创建Derived对象时,构造函数调用顺序如下:

  1. 基类构造函数:按照继承声明的顺序(Base2Base1Base3)调用。
    • 首先调用Base2的构造函数(传入参数b,即2),输出2
    • 然后调用Base1的构造函数(传入参数a,即1),输出1
    • 最后调用Base3的构造函数(无参数),输出*
  2. 成员对象构造函数:按照在类中声明的顺序(m1m2m3)调用。
    • 首先构造m1Base1类型,传入参数a即1),输出1
    • 然后构造m2Base2类型,传入参数b即2),输出2
    • 最后构造m3Base3类型,无参数),输出*

注意:虽然Derived的初始化列表中写了Base1(a), Base2(b),但基类的构造顺序只取决于继承顺序(Base2先于Base1),而不是初始化列表中的顺序。成员对象的构造顺序取决于它们在类中的声明顺序(m1m2m3),而不是初始化列表中的顺序。

参数传递

main中创建Derived对象时:

Derived d{1,2,3,4};

参数分别对应:

  • a=1, b=2, c=3, d=4(但cd在构造函数中未使用)。

输出结果

根据以上分析,输出顺序为:

  1. 基类Base2构造:输出2
  2. 基类Base1构造:输出1
  3. 基类Base3构造:输出*
  4. 成员m1Base1)构造:输出1
  5. 成员m2Base2)构造:输出2
  6. 成员m3Base3)构造:输出*

因此,最终输出为:2 1 * 1 2 *

完整输出

2
1
*
1
2
*

总结

代码输出为:

2
1
*
1
2
*

更多推荐