ProgrammingC++/バックエンド開発者

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; };

今、すべての共通ロジックは1つの「主要な」コンストラクタに集中し、他は呼び出しを委任しています。

主な特徴:

  • 初期化コードの重複を回避できます。
  • 信頼性と保守性が向上します。
  • コンストラクタ本体ではなく、初期化リスト内での委任。

騙しの質問。

コンストラクタ本体内の関数呼び出しを介して別のコンストラクタに委任できますか?

いいえ。別のコンストラクタの呼び出しは、初期化リストを通じてのみ可能であり、コンストラクタ本体内では行えません。コンストラクタの本体から関数を呼び出すと、オブジェクトのメンバーはすでに初期化されています。

コンストラクタ間で「リング」委任を作成するとどうなりますか?

リングデリゲーション(たとえば、AがBを、BがAをデリゲートすること)は、C++のコンパイルエラーを引き起こします。コンストラクタ間に無限の再帰が存在することはできません。

派生クラスのデリゲーティングコンストラクタを使用して、基底クラスのコンストラクタを呼び出すことはできますか?

いいえ。デリゲーティングコンストラクタは、同じクラス内でのみ機能します。基底コンストラクタを呼び出すには、別の構文を使用します:

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

タイプミスとアンチパターン

  • 過剰なデリゲーティングコンストラクタによる可読性の低下
  • リングデリゲーション — コンパイルエラー
  • デリゲーティングコンストラクタを通じて基底クラスのコンストラクタを呼び出そうとする試み

実生活の例

ネガティブケース

3つのコンストラクタがあり、それぞれが明示的にフィールドを初期化し、ロジックが同期されていない — 変更は1つのコンストラクタにのみ加えられ、他の2つは不正になります。

利点:

  • 書くのが簡単

欠点:

  • コンストラクタ間のロジックが異なるリスクが高い

ポジティブケース

1つの主要なコンストラクタが、他を委任し、すべての初期化ロジックが集中化されています。

利点:

  • 保守が容易で、ロジックの食い違いが排除されます。
  • コードの重複を最小限に抑えることができます。

欠点:

  • 初期化リストの構文に慣れる必要があります。