委托构造函数必须在初始化列表中调用同一类的其他构造函数,且不能与其他成员初始化共存;例如widget(int x) : widget(x, 0) {}。

委托构造函数怎么写,语法长什么样
C++11 引入的委托构造函数,本质是一个构造函数调用同一个类的另一个构造函数来完成初始化。它不是“把控制权交给别的类”,也不是“回调”,就是本类内部的构造函数复用。
关键点:委托必须出现在成员初始化列表中,且不能同时出现其他成员初始化;被委托的构造函数负责所有实际初始化工作。
class Widget {
public:
Widget(int x) : Widget(x, 0) {} // ✅ 委托给下面那个
Widget(int x, int y) : value(x + y) {} // ✅ 被委托的构造函数
private:
int value;
};
-
Widget(int x)的初始化列表里只有Widget(x, 0),不能再写value(42)或其他成员 - 委托目标必须是同一类的另一个构造函数,不能是基类或友元
- 委托语句必须是初始化列表中唯一一项,否则编译报错:
error: constructor delegation must be the only member initializer
为什么不能在构造函数体里调用另一个构造函数
因为 C++ 规定:构造函数体执行时,对象已经完成内存分配和成员初始化(包括基类、成员子对象)。此时再调用另一个构造函数,等于试图对一个已构造的对象“重新构造”——这既无定义,也违背对象生命周期规则。
常见错误现象:
立即学习“C++免费学习笔记(深入)”;
- 手动写
this->Widget(42)或Widget(42)→ 编译失败,或静默创建临时对象(完全不是你想要的效果) - 在构造函数体内复制一堆赋值逻辑,比如反复写
name = n; id = i; valid = true;→ 冗余、易错、难维护
所以委托不是“可选项”,而是唯一合法的构造函数复用方式。它把初始化逻辑收束到一处,避免赋值式补救(比如先默认构造再赋值),也规避了未初始化成员的风险。
委托链能嵌套几层?有没有坑
可以多层委托,但必须保证最终有一个不委托的构造函数(即“终点构造函数”),否则编译器会报循环依赖:
Widget() : Widget(0) {} // ❌ 错误:Widget(0) 又委托回 Widget()
Widget(int x) : Widget() {} // 循环了
实际使用中要注意:
- 委托链过深(>3 层)会让调用路径变模糊,调试时不容易追踪初始化顺序
- 所有委托构造函数的异常安全由终点构造函数决定:如果终点抛异常,前面所有委托都会按栈反向析构已构造的子对象,但不会执行任何“清理逻辑”
- 参数类型隐式转换可能触发意外委托:比如
Widget(double)和Widget(int)同时存在,传5.0可能调用前者而非你预期的后者
和初始化列表里的成员初始化冲突吗
会。委托构造函数和成员初始化互斥:一旦用了委托,初始化列表里就不能再初始化任何成员、基类或虚基类。
这意味着:
- 终点构造函数必须承担全部初始化责任,包括基类、虚基类、所有成员
- 如果你习惯在每个构造函数里单独初始化
std::string name,现在得统一挪到终点里 - 某些场景下反而更清晰:比如所有构造路径最终都走
Widget(Config cfg),那配置解析、校验、默认填充全在那里做,不用散落各处
容易被忽略的一点:委托不改变构造顺序。基类仍先于派生类构造,虚基类仍最前,成员仍按声明顺序构造——委托只是把“写在哪”的位置集中了,不是重排生命周期。
委托本身不带来运行时开销,但终点构造函数若做了大量计算或 I/O,所有委托路径都会继承这部分成本。别为了“看起来干净”而把耗时操作塞进终点构造函数里。








