由于构造函数的本质是对成员变量进行赋值,而并非进行初始化,因此如果成员函数中有const修饰的变量的话,就会导致该变量无法成为我们想要的值。这里就需要用到初始化列表来解决这种问题。
初始化列表:以一个冒号开始,接着是一个以逗号分隔的数据成员列表,每个"成员变量"后面跟一个放在括号中的初始值或表达式。
class length
{
public:
length(int len)
:_len(len)//初始化列表
{}
private:
const int _len;
};
const修饰的变量只有一次修改的机会,那就是在初始化的时候,而初始化列表可以将成员变量初始化为你所需要的值。
除了const修饰成员变量,还有两种情况必须要用到初始化列表:引用成员变量、不含默认构造函数的自定义类型成员。
引用成员变量:
class this_time
{
public:
this_time(int hour)
:_time(hour)
{}
private:
int& _time;
};
如果在构造函数中让_time=hour的话,就成了赋值,而使用初始化列表的话,就是int&_time=hour
不含默认构造函数的自定义成员类型:
class lunar
{
public:
lunar(int year)
:_year(year)
{}
private:
int _year;
};
class Date
{
public:
Date(int year,int month,int day)
:_year(year)
,_month(month)
,_day(day)
,_lun(2022)
{}
private:
int _year;
int _month;
int _day;
lunar _lun;
};
由于不含有默认构造函数,但是使用初始化列表也可将其初始化,因此我们推荐使用初始化列表来对成员进行初始化。
值得注意的是,初始化列表并不是根据初始化列表中的顺序来进行初始化的,而是根据声明的顺序进行的。
class A {
public:
A(int a)
:_a1(a)
,_a2(_a1)
{}
void Print() {
cout<<_a1<<" "<<_a2<<endl;
}
private:
int _a2;
int _a1;
};
int main() {
A aa(1);
aa.Print();
}
由于_a2是先进行声明的,所以先对其进行初始化,但是此时的_a1还未被初始化,所以_a2被初始化为了一个随机值。