目录
一.为什么要用构造函数初始化列表
常规的构造函数初始化方式
class Rectangle
{
public:
Rectangle(int width,int height)
{
m_width = width;
m_height = height;
}
};
在类外定义构造函数要指明该构造函数是哪个类的成员
class Rectangle
{
//do something
};
//类外定义类的构造函数
Rectangle::Rectangle()
{
//init something
}
但是,如果成员是const,引用,或者属于某种未提供默认构造函数的类,则必须通过构造函数初始化列表为这些成员提供初值,否则会报错。
这里成员a并没有报错,默认初始化,而b为const类型,c为引用类型,都会报未提供初始值错误
二.使用构造函数初始化列表的方式
ClassName(parameterList):dataField1{value1},dataField2{value2}
{
//something to do
}
构造函数初始化列表是在构造函数的基础上,在参数和函数体花括号之间,以一个冒号开始,插入的内容就是初始化列表。此处采用了C++11的列表初始化的方式插入,还可以使用dataField1(value1)这样的方式插入。
上面的构造函数使用初始化列表方式代码如下:
#include <iostream>
using namespace std;
class Rectangle
{
public:
Rectangle(); //默认构造函数
Rectangle(int val) :a(val), b(val), c(a){}; //构造函数初始化列表
void show()
{
cout << a << endl;
cout << b << endl;
cout << c << endl;
}
private:
int a;
const int b;
int &c;
};
int main()
{
Rectangle rectangle(1);
rectangle.show();
system("pause");
return 0;
}
或者:
class Rectangle
{
public:
Rectangle() :a(1), b(1), c(a){}; //构造函数初始化列表
void show()
{
cout << a << endl;
cout << b << endl;
cout << c << endl;
}
private:
int a;
const int b;
int &c;
};
int main()
{
Rectangle rectangle;
rectangle.show();
system("pause");
return 0;
}
对象数据类型必须在构造函数体之前初始化
这里具体是指Add对象的构造函数必须在Rectangle的构造函数体之前完成初始化
class Add
{
//do something
}
class Rectangle
{
public:
Rectangle(); //默认构造函数
/*
Rectangle()
{
add = Add(); //这样做就不能保证add构造函数在Rectangle函数体之前完成初始化
};
*/
Rectangle():add()
{
//do something
}; //类对象构造函数初始化列表
private:
Add add;
};
int main()
{
Rectangle rectangle;
}
三.构造函数成员初始化顺序
成员变量的初始化顺序只与成员变量在类中声明的顺序有关,与初始化列表中列出的变量的顺序无关。
但是,如果一个成员是用另一个成员来初始化的,那么这两个成员的初始化顺序就很关键了;
class A
{
public:
A(int val):b(val),a(b){} //实际上的顺序是a先初始化,所以报错:试图用未定义的b初始化a
private:
int a;
int b;
}
最好建议使用构造函数的参数作为成员的初始值
class A
{
public:
A(int val):b(val),a(val){} //实际上的顺序是a先初始化,所以报错:试图用未定义的b初始化a
private:
int a;
int b;
}