初始化列表:
以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个成员变量后面跟一个放在括号中的初始值或表达式。
例如:
class Date
{
public:
Date(int year, int month, int day): _year(year), _month(month), _day(day)
{
}
private:
int _year;
int _month;
int _day;
};
1.每个成员变量在初始化列表中只能出现一次(初始化只能初始化一次)
2.三类成员必须在初始化列表中进行初始化:引用成员变量,const成员变量,没有默认构造函数的自定义成员。
3.尽量使用初始化列表初始化,因为不管你是否使用初始化列表,对于自定义类型成员变量,一定会先使用初始化列表初始化。
4.成员变量在类中声明次序就是其在初始化列表中的初始化顺序,与其在初始化列表中的先后次序无关
思考下面这段代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class A {
public:
A(int a):a1(a),a2(a1)
{
cout << a1 << " " << a2 << endl;
}
private:
int a2;
int a1;
};
int main()
{
A a(1);
return 0;
}
输出结果:
a1=1, a2为随机值。
单参构造函数的隐式类型转换 explicit关键字
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
class A {
public:
A(int a) :_a(1)
{
cout << "A()" << endl;
}
private:
int _a;
};
int main()
{
A obj1(1);
A obj2 = obj1;
A obj3 = 20;
return 0;
}
阅读上面这段代码,看第18行,直接用整数20去初始化类A的对象obj3,这是不合逻辑的,但是这段代码在编译器中却是可以正常运行的。这是因为编译器内部进行了优化,在执行该语句时,编译器会先用整数20初始化一个临时的无名对象,然后用该临时对象给obj3进行赋值,这种现象称为单参构造函数的隐式类型转换。(注意:只有单参数的构造函数可以编译通过!!!)
那么如何解决该问题呢?
此处我们引入explicit关键字,在定义构造函数时,在函数名之前加上explicit关键字就可以避免发生这种情况。