初始化列表
1、初始化列表用法:
以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
class Date
{
public:
//构造函数
Date(int year = 2000, int month = 1, int day = 1)
:_year(year) //初始化列表
,_month(month)
,_day(day)
{}
private:
int _year;
int _month;
int _day;
};
2、初始化列表特性
1、每个变量只能初始化一次,多次会报错。
class Date
{
public:
//构造函数
Date(int year = 2000, int month = 1, int day = 1)
:_year(year)
, _month(month)
, _day(day)
, _month(month) //初始化列表不能多次初始化
{}
private:
int _year;
int _month;
int _day;
};
2、初始化列表和构造函数赋初值可以混用,混用时两者不冲突,但初始化列表只能初始化一次
class Date
{
public:
//构造函数
Date(int year = 2000, int month = 1, int day = 1)
:_year(year)
,_month(month)
,_day(day)
//_day(10) 错误
//_day在初始化列表里被初始化了两次,不允许。
{
_day = day;
//_day可以被初始化列表然后被构造函数赋初值。
}//可混用
private:
int _year;
int _month;
int _day;
};
3、const成员变量、引用成员变量、没有默认构造函数的自定义类型成员只能在初始化列表初始化。其他变量可初始化列表初始化也可以构造函数赋初值。
class Date
{
public:
Date(int year = 2000, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _val(2) //const成员变量,引用必须使用初始化列表进行初始化
,_ref(year);
{
_day = day;
//_val = 1; //const成员变量,引用不能在函数体内初始化
//_ref = year;
}
private:
int _year;
int _month;
int _day;
const int _val;
int& _ref;
};
没有默认构造函数的自定义类型必须在初始化列表初始化。
#include <iostream>
using namespace std;
class A
{
public:
//默认构造函数是不用传参就可以调用的构造函数,共有3种:
//1.无参默认构造函数
//2.全缺省的默认构造函数
//3.没有显式写,编译器自动生成的默认构造函数。
A(int x)//不属于以上任何一种,所以A类的对象没有默认构造函数,但是有构造函数,即带参构造。
{
_x = x;
}
private:
int _x;
};
class Date
{
public:
//构造函数
Date(int year = 2000, int month = 1, int day = 1)
: _year(year)
, _month(month)
, _a(3)//没有默认构造函数的自定义类型成员变量必须在初始化列表进行初始化.
{
_day = day;
}
private:
int _year;
int _month;
int _day;
A _a;
};
const成员变量、引用成员变量、没有默认构造函数的自定义类型成员必须在初始化列表初始化的原因:
1、初始化列表是对象中变量定义的地方。
2、const成员变量在定义时就要赋初值。
3、引用成员变量在定义的时候要赋初值。
4、没有默认构造函数的自定义类型成员变量在定义时若不采用初始化列表,会找不到默认构造函数而报错。
4、建议尽量使用初始化列表初始化,因为不管是否使用初始化列表,虽然对于内置类型没有差别,但是对于自定义类型成员变量,是必须使用初始化列表初始化。
5、成员变量初始化的顺序就是成员变量在类中的声明次序,与初始化列表中的先后次序无关。
#include <iostream>
using namespace std;
class A
{
public:
A(int a)
: _a1(a)
, _a2(_a1)
{}
void Print()
{
cout << _a1 << " " << _a2 << endl;
}
private:
int _a2;//先声明_a2
int _a1;//后声明_a1
};
int main() {
A aa(1);
aa.Print();
}
运行结果:
因为先声明—_a2,所以_a2是随机值,_a1=1;
所以建议声明和初始化列表的初始化顺序一致。