委托构造函数的基本写法是ClassName(args) : ClassName(other_args) { },必须在初始化列表中调用同名类的另一构造函数,且初始化列表中不得包含其他成员或基类初始化;被委托构造函数的初始化列表和函数体均会执行,当前构造函数体在其后运行;禁止循环委托。

委托构造函数的基本写法
委托构造函数不是新语法糖,而是让一个构造函数把初始化工作“转包”给同一个类的另一个构造函数。关键点在于:必须在成员初始化列表里调用,且不能同时初始化任何其他成员或基类。
常见错误是写成函数体内调用:MyClass(10); —— 这只是创建临时对象,完全不参与当前对象构造。
- 语法只能是
MyClass(args) : MyClass(other_args) { },冒号后紧跟被委托的构造函数调用 - 被委托的构造函数会完整执行它的初始化列表和函数体,当前构造函数的函数体在它之后才运行
- 不能委托给自己(直接或间接),否则编译报错
error: constructor delegation loops
为什么委托后不能再初始化成员
因为 C++ 标准规定:如果用了委托构造,初始化列表里只能有被委托的构造函数调用,不能再出现 member(value) 或 BaseClass(args)。这是硬性限制,不是风格建议。
典型错误示例:Person(string n) : Person(), name(n) { } —— 编译失败,name(n) 不合法。
- 想复用逻辑又需定制字段?把定制部分挪到函数体里,比如
name = n; - 委托链最多一层(A → B),B 不能再委托回 A,也不能再委托给 C 后 C 又委托回 A
- 委托目标可以是带默认参数的构造函数,但显式调用时仍要匹配签名,不能依赖默认值“补位”
委托构造和默认参数的取舍
很多人第一反应是“那我全用默认参数不就完了”,但二者语义不同:默认参数生成多个重载构造函数,委托构造只生成一个,且能控制执行顺序和副作用。
比如日志记录、资源预分配等操作,放在被委托的构造函数里可确保只执行一次;而默认参数版本可能每个构造函数都重复执行。
- 需要共享初始化逻辑(如验证输入、分配缓冲区)→ 优先委托构造
- 只是参数组合简单、无副作用 → 默认参数更轻量、调试更直观
- 混合使用要注意:带默认参数的构造函数可以作为委托目标,但反过来不行——你不能在默认参数构造函数里再去委托另一个构造函数,否则初始化列表冲突
实际项目中容易漏掉的细节
委托构造函数不会自动帮你处理 const 成员、引用成员或没有默认构造函数的成员。这些字段必须在被委托的那个构造函数的初始化列表里搞定,否则编译不过。
比如类里有个 const int id;,而你委托到一个没初始化 id 的构造函数,就会报 uninitialized const member。
- 检查所有被委托的构造函数是否满足:每个 const/引用/无默认构造的成员都被显式初始化
- 继承场景下,委托构造不能绕过基类初始化——基类初始化必须出现在被委托构造函数的初始化列表中
- 移动构造函数也可以被委托,但注意别意外触发拷贝(比如传参用了值传递而非右值引用)
委托构造真正难的不是语法,而是理清初始化责任边界:谁负责设初值、谁负责做检查、谁负责记日志。一旦委托链变长,出问题时堆栈里看不到中间层,debug 要盯着初始化列表逐行比对。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











