编程C++/后端开发人员

在C++中,什么是委托构造函数,何时及为何使用它们?

用 Hintsage AI 助手通过面试

答案。

问题的历史

在C++11标准之前,如果需要编写多个具有不同参数的构造函数,必须在每个构造函数中重复初始化代码,因为无法在类的构造函数内部调用其他构造函数。

问题

无法在其他构造函数中使用已经存在的初始化逻辑导致代码重复和在更改初始化逻辑时的错误:更新一个构造函数时,容易忘记其他构造函数。

解决方案

随着C++11的推出,出现了“委托构造函数”的机制,使得一个类的构造函数可以通过初始化列表的语法调用该类的另一个构造函数。

代码示例:

class Widget { public: Widget() : Widget(0, "default") {} Widget(int n) : Widget(n, "user") {} Widget(int n, std::string name) : size(n), label(name) {} private: int size; std::string label; };

现在,所有的公共逻辑集中在一个“主”构造函数中,其他构造函数委托调用。

关键特性:

  • 避免了初始化代码的重复
  • 提高了可靠性和可维护性
  • 在初始化列表中进行委托,而不是在构造函数体内

陷阱问题。

可以通过在构造函数体内调用函数来委托调用给另一个构造函数吗?

不可以。构造函数之间仅能通过初始化列表调用,而不能在构造函数体内部调用。如果在构造函数体内调用函数,成员对象将已经被初始化。

如果创建构造函数之间的“委托环”会发生什么?

循环委托(例如,A委托B,而B又委托A)会导致C++编译错误:构造函数之间不能有无限递归。

可以通过派生类的委托构造函数委托给基类构造函数吗?

不可以。委托构造函数只能在一个类内部工作。要调用基类构造函数,需要使用单独的语法:

class Base { public: Base(int) {} }; class Derived : public Base { public: Derived() : Base(42) {} };

常见错误和反模式

  • 在委托构造函数数量过多时破坏可读性
  • 循环委托 — 编译错误
  • 尝试通过委托构造函数委托给基类构造函数

实际示例

负面案例

三个构造函数,每个都显式初始化字段,逻辑不同步 — 仅更改一个构造函数,其他两个将不正确。

优点:

  • 简单易写

缺点:

  • 构造函数之间逻辑差异的高风险

正面案例

一个主构造函数,其他构造函数委托于它,所有初始化逻辑集中。

优点:

  • 易于维护,逻辑差异被排除
  • 最小化代码重复

缺点:

  • 需要习惯初始化列表的语法