首先解释一下初始化列表的常识,即初始化列表的初始化顺序只与定义顺序有关,与列表中的顺序无关。
举个栗子:
#include<iostream>
using namespace std;
int t = 0;
class A {
public :
int x;
A() {
cout << "A default constructor" << endl;
}
A(int _x) : x(_x) {
;
}
};
class B : public A {
public :
int y;
B() : y(t++), A(t++) {}
};
int main() {
B b;
cout << b.x << endl;
cout << b.y << endl;
return 0;
}
上面程序中运行结果是:
0
1
初始化列表中子类属性 y 在前面, 但是 y 的值却比 x 的值大(t 表示时间戳),说明 y 比 x 后初始化,这是因为父类一定会比子类属性定义地早,所以父类会先被初始化,而父类初始化是用父类自己的构造函数初始化的。
比如下面这段例子:
#include<iostream>
using namespace std;
int t = 0;
class A {
public :
int x;
A() {
cout << "A default constructor" << endl;
}
A(int _x) : x(_x) {
//cout << "A constructor" << endl;
}
};
class B : public A {
public :
int y;
B() : y(t++) {
cout << "B constructor" << endl;
}
};
int main() {
B b;
//cout << b.x << endl;
//cout << b.y << endl;
return 0;
}
这里子类B中没有调用父类的构造函数,但是继承前一定会先构造父类(这一句话我不确定,因为接口类是无法构造的,但是都能调用子类的构造函数了,说明子类已经实现了纯虚函数,所以可以通过子类调用父类的构造函数),而调用父类的构造函数就能初始化父类的成员属性,既然已经初始化了为什么还需要子类的初始化列表再初始化父类成员属性一次呢?
所以C++中规定了父类的成员属性只能用父类的构造函数初始化。