构造函数重载允许类定义多个参数列表不同的构造函数,编译器依实参和初始化语法选择匹配项;需满足可区分性,避免默认参数冲突;委托构造、explicit限定和initializer_list优先级等规则共同影响调用行为。

构造函数重载在C++中允许一个类定义多个构造函数,只要它们的参数列表不同(类型、数量或cv限定符不同),编译器就能根据初始化时提供的实参自动选择最匹配的一个。初始化方式则决定了调用哪个重载构造函数,也影响对象是否能被正确创建。
构造函数重载的基本规则
重载构造函数必须满足“可区分性”:参数列表不能仅靠返回类型或默认参数差异来区分;不能有多个构造函数接受完全相同的实参类型组合。
- 参数类型不同即可重载,例如 A(int) 和 A(double)
- 参数个数不同也可重载,例如 A()、A(int)、A(int, int)
- 带默认参数的构造函数要小心:A(int x = 0) 和 A() 会冲突,因为两者都可被无参调用
- 委托构造函数(C++11起)允许一个构造函数调用同类另一个构造函数,但只能出现在初始化列表中,且自身不能有其他成员初始化
直接初始化 vs 拷贝初始化
初始化语法不同,可能触发不同重载,甚至影响是否允许隐式转换。
- 直接初始化:A a(1); 或 A a{1}; —— 编译器尝试匹配所有可行构造函数,包括 explicit 构造函数
- 拷贝初始化:A a = 1; 或 A a = A(1); —— 只考虑非 explicit 构造函数,且可能多一次隐式转换(C++17前可能省略,但语义上仍要求可拷贝/移动)
- A a{1, 2}; 是列表初始化,优先匹配 initializer_list 构造函数(如果存在),否则按聚合或逐个参数匹配
常见初始化方式与对应构造函数调用
同一类的不同初始化写法,可能调用完全不同的重载构造函数。
立即学习“C++免费学习笔记(深入)”;
- MyClass m; → 默认构造函数 MyClass()
- MyClass m(42); → 匹配 MyClass(int)
- MyClass m = 42; → 若 MyClass(int) 是 explicit,则编译失败;否则调用它
-
MyClass m{3.14}; → 若有 MyClass(double),且无 MyClass(std::initializer_list
) ,则调用前者;若有后者,优先调用后者 - MyClass m{}; → 值初始化,调用默认构造函数(若为类类型)或零初始化(若为POD)
explicit 关键字的作用与陷阱
explicit 用于防止非预期的隐式类型转换,只对单参数构造函数(或其余参数均有默认值)有意义。
- 声明为 explicit MyClass(int) 后,MyClass m = 10; 非法,但 MyClass m(10); 或 MyClass m{10}; 合法
- C++11起,explicit 也支持修饰转换运算符,限制隐式转换目标类型
- 多个参数的构造函数加 explicit 无意义(本来就不会隐式调用),但 C++11 允许语法上存在,C++17 起才禁止
基本上就这些。构造函数重载和初始化方式紧密耦合,理解它们的关键是记住:编译器选函数看实参类型和初始化语法,而 explicit 和 initializer_list 会显著改变匹配行为。









