类的数据成员的构造方式有赋值初始化和列表初始化。
赋值初始化:在函数体内初始化,这种方法是在所有数据成员分配内存空间之后才进行的。
列表初始化:在冒号后使用初始化列表进行初始化。列表初始化是在给数据成员分配内存空间时就进行初始化,就是说分配一个数据成员只要冒号后有此数据成员的赋值表达式(此表达式必须是括号赋值表达式),那么分配了内存空间后在进入函数体之前给数据成员赋值,而此时函数体还未执行。
从效率上看,赋值初始化
先进行了一次构造,而后又进行了一次赋值,而列表初始化仅调用一次成员的构造函数并赋值,无疑,效率上列表初始化要高很多。
但使用列表初始化有一个问题需要注意,它是按照声明的顺序初始化的,而不是按照出现在初始化列表中的顺序。
例如
#include<iostream>
using namespace std;
class people
{
public:
int weight;
int hight;
people(int h,int w):hight(h),weight(hight+1)
{
}
};
int main()
{
people yang(175,130);
cout<<"小杨的体重为"<<yang.weight<<endl;
cout<< "小杨的身高为"<<yang.hight<<endl;
return 0;
}
按照我写的初始化的顺序来看,会输出我的身高是175,体重是176,但是实际上并不是如此
原因就是编译器初始化的顺序是按照class内声明的顺序,如上述代码中,会先初始化weight,再初始化hight,而初始化weight时,hight还未构造,所以就出现我们不想要的情况。
有两种方法避免它,一个是总是按照你希望它们被初始化的顺序声明成员;第二个是,如果你决定使用初始化列表,总是按照它们声明的顺序罗列这些成员。这将有助于消除混淆。(qaq)
一个派生类的构造函数执行顺序如下:
1.虚拟基类的构造函数(多个虚拟基类则按照继承的顺序执行构造函数)
2.基类的构造函数(多个普通基类也要按照继承的顺序执行构造函数)
3.类类型的成员对象的构造函数
4.派生类自己的构造函数