在C++中,派生类对象创建时构造函数的执行顺序遵循以下规则:
虚拟基类构造函数、普通基类构造函数、派生类成员对象构造函数、派生类自身构造函数。
虚拟基类构造函数:
优先级最高:无论继承顺序如何,所有虚基类的构造函数会最先执行,且仅执行一次(避免菱形继承重复构造)。
调用规则:虚基类构造函数按其在继承体系中的声明顺序执行,而非派生类中继承中的顺序。
普通基类构造函数:
执行顺序:按照派生类定义中的基类的声明顺序调用(从左到右)。
Class D:public B1,virtual public B2{
};
上述代码的构造顺序是:B2(虚基类)、B1、D。
参数传递:若基类无默认构造函数,需在派生类初始化列表中显示传递参数。
派生类成员对象构造函数:
成员初始化顺序:按类中成员变量的声明顺序执行,与初始化列表中的顺序无关。
Class Derived{
A a;
B b;
public:
Derived():b(),a(){}
}
上述代码的实际执行顺序是A()、B()。
派生类自身构造函数:
最后执行:在完成基类和成员对象初始化后,执行派生类构造函数体中的代码。
Class VirtualBase{
public:
VritualBase(){
cout<<"VrituaBase的构造函数"<<endl;
}
};
Class Base1{
public:
Base1(){
cout<<"Base1的构造函数"<<endl;
}
}
Class Base2{
public:
Base2(){
cout<<"Base2的构造函数"<<endl;
}
}
Class Derived:public Base1,vritual public VritualBse,public Base2{
int x;
public:
Derived():Base(),x(10){
cout<<"Deerived的构造函数"<<endl;
}
}
上述代码的输出顺序:
VritualBase构造、Base1构造、Base2构造、Derived构造。
关键区别:
顺序(对象类型) | 调用依据 |
虚基类 | 继承体系中的声明顺序(唯一一次) |
普通基类 | 派生类定义中的继承顺序 |
成员对象 | 类内成员变量的声明顺序 |
派生类自身 | 构造函数体中的代码 |
常见误区:
虚基类与普通基类顺序无关:虚基类构造函数始终优于普通基类,即使普通基类在继承列表中更靠前。
成员对象初始化顺序:与初始化列表无关,仅由类内声明顺序决定。
虚继承的必要性:虚基类用于解决菱形继承的二义性,确保基类只被构造一次。