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つの主要なコンストラクタが、他を委任し、すべての初期化ロジックが集中化されています。
利点:
欠点: