基本クラス A があり、クラス B がそこから派生しているとしましょう。B からクラス C など ..... Z から Y。
クラス Z をインスタンス化する場合、クラス A のデータ メンバの初期化は誰が担当しますか?
クラスから継承する場合、基本クラスのコンストラクターは、派生クラスのコンストラクターより前に呼び出されます。初期化子リストを使用して、渡されるものを制御できます。
struct A
{
A();
A(int);
}
struct B
{
B(){} // A() is called implicitly.
B(int x) : A(x) {} // A(int) is called explicitly.
}
私の知る限り、A のコンストラクターは、A のデータ メンバーの初期化を担当します。これは、クラスがトップダウン、または Base-before-Derived から構築されるためです。これが、定義されている派生クラスがまだ作成されていないため、コンストラクターで純粋仮想メンバー関数を使用できない理由です。
すべてのクラスのすべてのコンストラクターは、即時の非仮想基本クラスをすべて構築します。これは、セットアップで何が起こるかを再帰的に説明します。
対照的に、仮想基底クラスは、最も派生したクラスのコンストラクターによって構築されます。
これは、基本コンストラクターを明示的に言及する典型的な例です。
struct A { A(int, int) { /* ... */ ; };
struct B : A { B(char, bool) : A(2, 3) { /* ... */ };
struct C : B { C() : B('x', false) { /* ... */ };
C c; // calls A::A(2, 3), then B::B('x', false), then C::C()
チェーンに沿って派生したクラスは、アクセシビリティに応じてデータ メンバーの初期化 を担当できます。
一般的な方法の 1 つは、クラス A のコンストラクターにデータ メンバーの値を要求させることです。クラス B は、これらの変数をそのコンストラクターなどに追加します。
クラスAからZのいずれかである可能性があり、状況によって完全に異なります. クラス A がそのコンストラクターで param ab と c を受け取る場合、クラス B はこれらを提供する必要があります。また、コンストラクターで abc が渡されることを期待する場合、これらを提供するのはクラス C になります。ただし、子クラスは、コンストラクターに渡されていない値を提供することを選択する場合があるため、後続の子はこの値を提供する必要がなくなります。