目录
往期文章👇
一、构造函数初始化列表
构造函数初始化还有⼀种⽅式,就是++初始化列表++
初始化列表的使⽤⽅式是:
以⼀个++冒号开始++,接着是⼀个以++逗号分隔++的数据成员列表,每个成员变量后⾯跟⼀个放在++括号++中的初始值或表达式。
代码示例:
cpp
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️⃣ 没有默认构造的类类型变量
这些变量必须放在初始化列表位置进⾏初始化,否则会编译报错。
代码示例:
cpp
class Time
{
public:
Time(int hour)
:_hour(hour)
{
cout << "Time()" << endl;
}
private:
int _hour;
};
class Date
{
public:
Date(int& x, int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
,_t(12)
,_n(1)
,rx(x)
{}
// error C2512: "Time": 没有合适的默认构造函数可⽤
// error C2530 : "Date::_ref" : 必须初始化引⽤
// error C2789 : "Date::_n" : 必须初始化常量限定类型的对象
private:
int _year;
int _month;
int _day;
const int _n;
int& rx;
Time _t;
};
🙃 C++11⽀持在成员变量声明的位置给缺省值,这个缺省值主要是给没有显⽰在初始化列表初始化的成员使⽤的。
举个例子,首先是有在初始化列表初始化的成员:
cpp
class Date
{
public:
Date(int year, int month, int day)
:_year(year)
,_month(month)
,_day(day)
{}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year = 1;
int _month = 1;
int _day = 1;
};
int main()
{
Date d1(2025, 10, 13);
d1.Print();
return 0;
}
可以发现正常输出d1传入的日期:2025-10-13
如果没有在初始化列表初始化的成员,C++11⽀持在成员变量声明的位置给缺省值:
cpp
class Date
{
public:
Date(int year, int month, int day)
:_year(year)
{}
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}
private:
int _year = 1;
int _month = 1;
int _day = 1;
};
int main()
{
Date d1(2025, 10, 13);
d1.Print();
return 0;
}
我们可以看到这时候 _month 和**_day** 的缺省值都定为1,因此当我们运行程序的时候发现输出的结果为:2025-1-1
因此我们可以总结一下初始化列表的知识点:
- 尽量使⽤初始化列表初始化,因为那些你不在初始化列表初始化的成员也会⾛初始化列表,如果这个成员在声明位置给了缺省值,初始化列表会⽤这个缺省值初始化。
😉如果你没有给缺省值,对于没有显⽰在初始化列表初始化的内置类型成员是否初始化取决于编译器,C++并没有规定。
😍对于没有显⽰在初始化列表初始化的⾃定义类型成员会调⽤这个成员类型的默认构造函数,如果没有默认构造会编译错误。
😘⽆论是否显⽰写初始化列表,每个构造函数都有初始化列表。
🥲⽆论是否在初始化列表显⽰初始化,每个成员变量都要⾛初始化列表初始化。

- 初始化列表中按照成员变量在类中声明顺序进⾏初始化,跟成员在初始化列表出现的的先后顺序⽆关,建议声明顺序和初始化列表顺序保持⼀致。
用一个题目进行解释👇:
😇下⾯程序的运⾏结果是什么?
A. 输出 1 1
B. 输出 2 2
C. 输出 1 随机值
cpp
class A
{
public :
A(int a)
: _a1(a)
, _a2(_a1)
{}
void Print()
{
cout << _a1 << " " << _a2 << endl;
}
private:
int _a2 = 2;
int _a1 = 2;
};
int main()
{
A aa(1);
aa.Print();
}
程序运行结果如下👇:

🤩从运行结果可以看出,初始化列表中是按照成员变量在类中声明顺序进⾏初始化,而跟成员在初始化列表出现的的先后顺序⽆关。
二、类型转换
(1) C++⽀持内置类型隐式类型转换为类类型对象,需要有相关内置类型为参数的构造函数。
(2) 构造函数前⾯加explicit就不再⽀持隐式类型转换。
(3) 类类型的对象之间也可以隐式转换,需要相应的构造函数⽀持。
cpp
class A
{
public:
// 构造函数explicit就不再⽀持隐式类型转换
// explicit A(int a1)
A(int a1)
:_a1(a1)
{}
//explicit A(int a1, int a2)
A(int a1, int a2)
:_a1(a1)
,_a2(a2)
{}
void Print()
{
cout << _a1 << " " << _a2 << endl;
}
int Get() const
{
return _a1 + _a2;
}
private:
int _a1 = 1;
int _a2 = 2;
};
class B
{
public:
B(const A& a)
: _b(a.Get())
{}
private:
int _b = 0;
};
int main()
{
// 1构造⼀个A的临时对象,再⽤这个临时对象拷⻉构造aa3
// 编译器遇到连续构造+拷⻉构造->优化为直接构造
A aa1 = 1;
aa1.Print();
const A& aa2 = 1;
// C++11之后才⽀持多参数转化
A aa3 = { 2,2 };
// aa3隐式类型转换为b对象
// 原理跟上⾯类似
B b = aa3;
const B& rb = aa3;
return 0;
}
💯如果这篇文章对你有用的话,请继续关注!