次のように、3 つのクラスのクラス構造があり、そのうちの 2 つは 3 番目の基本クラスです。
class A {
};
class B {
};
class C : public A, public B {
};
のインスタンスC
が破棄される場合、基本クラスA
とB
破棄される順序は? これに関する規則はありますか?
次のように、3 つのクラスのクラス構造があり、そのうちの 2 つは 3 番目の基本クラスです。
class A {
};
class B {
};
class C : public A, public B {
};
のインスタンスC
が破棄される場合、基本クラスA
とB
破棄される順序は? これに関する規則はありますか?
ルールがあります (C++11 §12.4):
デストラクタの本体を実行し、本体内に割り当てられた自動オブジェクトを破棄した後、クラス X のデストラクタは、X の直接の非バリアント非静的データ メンバーのデストラクタ、X の直接基底クラスのデストラクタを呼び出します。最も派生したクラス (12.6.2) の型であり、そのデストラクタは X の仮想基本クラスのデストラクタを呼び出します。すべてのデストラクタは、修飾名で参照されているかのように呼び出されます。つまり、より派生したクラスで可能な仮想オーバーライド デストラクタは無視されます。ベースとメンバーは、コンストラクターの完了と逆の順序で破棄されます(12.6.2 を参照)。デストラクタ内の return ステートメント (6.6.3) は、呼び出し元に直接戻らない場合があります。呼び出し元に制御を渡す前に、メンバーとベースのデストラクタが呼び出されます。配列の要素のデストラクタは、それらの構築とは逆の順序で呼び出されます (12.6 を参照)。
構築順序は (§12.6.2/10):
非委任コンストラクターでは、初期化は次の順序で進行します。
— 最初に、最も派生したクラス (1.8) のコンストラクターの場合のみ、仮想基底クラスは、基底クラスの有向非巡回グラフの深さ優先の左から右への走査に現れる順序で初期化されます。 -to-right」は、派生クラス base-specifier-list 内の基底クラスの出現順序です。
— 次に、直接基底クラスは、base-specifier-list に表示される宣言順に初期化されます (mem-initializer の順序に関係なく)。
— 次に、非静的データ メンバーは、クラス定義で宣言された順序で初期化されます (これも mem-initializer の順序に関係なく)。
— 最後に、コンストラクター本体の複合ステートメントが実行されます。[ 注: 宣言の順序は、基本サブオブジェクトとメンバー サブオブジェクトが初期化の逆の順序で確実に破棄されるようにするために義務付けられています。— エンドノート]
したがって、単純なケースでは、基本コンストラクターはクラスが宣言にリストされている順序で呼び出され、デストラクタはその順序の逆で実行されます。