C++三大隐藏坑:初始化列表、隐式转换、static成员你真的用对了吗?
📅 2026 · C++ 系列笔记C++面向对象构造函数
目录
1. 再探构造函数——初始化列表
哪些成员必须用初始化列表?
C++11 成员变量缺省值
2. 类型转换与 explicit
3. static 静态成员
1. 再探构造函数——初始化列表
之前写构造函数时,我习惯在函数体内用赋值语句初始化成员变量。但 C++ 其实提供了另一种更正规的方式:初始化列表。它以冒号:开头,紧跟在参数列表之后。
C++
class Date { public: Date(int year, int month, int day) : _year(year) // 初始化列表 , _month(month) , _day(day) {} private: int _year; int _month; int _day; };
哪些成员必须用初始化列表?
- 引用成员变量(
int& _ref):引用必须在定义时初始化 - const 成员变量(
const int _n):常量不能赋值,只能初始化 - 没有默认构造函数的类类型成员:编译器不知道怎么"默认构造"它
⚠️ 初始化列表中成员的初始化顺序,由它们在类中声明的顺序决定,与初始化列表里写的顺序无关!建议两者保持一致,避免踩坑。
C++(必须走初始化列表的示例)
class Time { public: Time(int hour) : _hour(hour) {} // 无默认构造 private: int _hour; }; class Date { public: Date(int& x, int year = 1, int month = 1, int day = 1) : _year(year) , _month(month) , _day(day) , _t(12) // 必须在这里给 Time 传参 , _ref(x) // 引用必须在初始化列表 , _n(1) // const 必须在初始化列表 {} private: int _year, _month, _day; Time _t; // 无默认构造 int& _ref; // 引用 const int _n; // const };
C++11 成员变量缺省值
C++11 支持在成员声明处给缺省值,这个缺省值是给初始化列表"兜底"用的——如果初始化列表没有显式初始化该成员,就用这个缺省值。
class Date { public: Date() : _month(2) {} // 只覆盖 _month,其余用缺省值 private: int _year = 1; // 缺省值 int _month = 1; int _day; // 无缺省值,初始化未定义 Time _t = 1; const int _n = 1; };🧩 经典考题:下面程序输出什么?
C++
class A { public: A(int a) : _a1(a) , _a2(_a1) // ⚠️ 初始化顺序由声明顺序决定! {} void Print() { cout << _a1 << " " << _a2; } private: int _a2 = 2; // 声明在前,先初始化 int _a1 = 2; // 声明在后,后初始化 };A. 1 1B. 2 2C. 编译报错F. 1 随机值
2. 类型转换与 explicit
C++ 允许内置类型通过对应的构造函数隐式转换为类对象,这个特性有时很方便,但也容易让代码语义不清晰。
C++ class A { public: A(int a1) : _a1(a1) {} A(int a1, int a2) : _a1(a1), _a2(a2) {} private: int _a1 = 1; int _a2 = 2; }; // 单参数隐式转换(构造一个临时对象,编译器优化为直接构造) A aa1 = 1; const A& aa2 = 1; // 合法,const 引用延长临时对象生命周期 // C++11 支持多参数隐式转换 A aa3 = {2, 2};💡 在构造函数前加explicit可禁止隐式类型转换,让代码意图更明确。推荐对单参数构造函数加explicit,避免意外转换。
3. static 静态成员
static 成员分为静态成员变量和静态成员函数,两者都属于整个类,而不属于某个具体对象。
- 静态成员变量存放在静态区,所有对象共享同一份
- 静态成员变量必须在类外定义初始化(不能在声明处给缺省值,因为它不走构造函数)
- 静态成员函数没有 this 指针,因此只能访问静态成员
- 访问方式:
类名::静态成员或对象.静态成员(仍受访问限定符限制)
C++(统计存活对象数量)
class A { public: A() { ++_scount; } A(const A& t) { ++_scount; } ~A() { --_scount; } static int GetACount() { return _scount; } private: static int _scount; // 类内声明 }; int A::_scount = 0; // 类外初始化 int main() { cout << A::GetACount() << endl; // 0 A a1, a2; A a3(a1); cout << A::GetACount() << endl; // 3 return 0; }✅ 经典应用:利用 static 成员实现"计算程序中创建了多少个对象"、"求 1+2+…+n(变长数组技巧)"等。
