#define _CRT_SECURE_NO_WARNINGS 1
#include
using namespace std;
class Date {
public:
Date(int _year = 2025, int _month = 2, int _day = 4)
{
year = _year;
month = _month;
day = _day;
}
private:
int year;
int month;
int day;
};
我们看上面的代码,在我们创建一个类的时候编译器会通过构造函数给类对象中的各个成员变量赋初值,但是这样不能称作类对象成员的初始化,因为在函数体中我们可以多次的赋值,例如这样:
class Date {
public:
Date(int _year = 2025, int _month = 2, int _day = 4)
{
year = _year;
month = _month;
day = _day;
month = 1;
}
private:
int year;
int month;
int day;
};
而初始化列表只能初始化一次。
什么是初始化列表?
初始化列表: 以⼀个冒号开始,接着是⼀个以逗号分隔的数据成员列表,每个"成员变量"后面跟⼀个放在括号中的初始值或表达式。
初始化列表的用法:
class Date {
public:
Date(int _year = 2025, int _month = 2 , int _day = 4)
:year(_year)
,month(_month)
,day(_day)
{
}
private:
int year;
int month;
int day;
};
(1)初始化列表只能初始化一次,多次初始化会报错。
(2)const成员变量、引用成员变量、没有默认构造函数的自定义类型成员只能在初始化列表初始化。
(3)尽量使用初始化列表初始化,因为不管有没有用初始化列表,虽然说内置类型没有差别,但是对于自定义类型成员,一定先使用初始化列表初始化。
(4)成员变量初始化的顺序就是成员变量在类中的声明次序,与初始化列表中的先后顺序无关。
先从第一点讲起:
初始化列表只能初始化一次,多次初始化会报错。
class Date {
public:
Date(int _year = 2025, int _month = 2 , int _day = 4)
:year(_year)
,month(_month)
,day(_day)
,month(_month) //这样就是初始化多次,编译器会报错
{
}
private:
int year;
int month;
int day;
};
重点: 编译器允许构造函数赋初值和初始化列表初始化混用,混用时两者不冲突,但是混用时初始化列表还是要遵循只能初始化一次成员变量的原则。
下面我们到第二点:
const成员变量、引用成员变量、没有默认构造函数的自定义类型成员只能在初始化列表初始化。
1、const成员变量必须在定义的时候初始化
class Date {
public:
Date(int _year = 2025, int _month = 2 , int _day = 4)
:year(_year)
,month(_month)
,day(_day)
,n(1)
{
//n = 1; //必须放在初始化列表中,不能放在函数体内初始化
}
private:
int year;
int month;
int day;
const int n = 1;
};
2、引用成员变量必须在定义的时候初始化
class Date {
public:
Date(int _year = 2025, int _month = 2 , int _day = 4)
:year(_year)
,month(_month)
,day(_day)
,n(year)
{
//n = year; //必须放在初始化列表中,不能放在函数体内初始化
}
private:
int year;
int month;
int day;
int& n;
};
3、没有默认构造函数的自定义类型成员变量
首先我们复习一下什么是默认构造函数:
①无参默认构造函数
②带参全缺省的默认构造函数
③我们没有写,编译器自动生成的默认构造函数
#include
using namespace std;
class A
{
public:
A(int x)
{
cout << "A(int x)" << endl;
_x = x;
}
private:
int _x;
};
class Date
{
public:
//构造函数
Date(int year = 2022, int month = 4, int day = 19)
: _year(year)
, _month(month)
, _a(20)
{
_day = day;
}
private:
int _year;
int _month;
int _day;
A _a;
};
成员变量初始化的顺序就是成员变量在类中的声明次序,与初始化列表中的先后顺序无关。
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,后声明了_a1,初始化的时候先初始化_a2再初始化_a1。