42

オブジェクトの作成に関するちょっとした質問。次の 2 つのクラスがあるとします。

struct A{
    A(){cout << "A() C-tor" << endl;}
    ~A(){cout << "~A() D-tor" << endl;}
};

struct B : public A{
    B(){cout << "B() C-tor" << endl;}
    ~B(){cout << "~B() D-tor" << endl;}

    A a;
};

そして主に次のインスタンスを作成しますB

int main(){
    B b;
}

Bから派生しA、 type のフィールドも持っていることに注意してくださいA

ルールを理解しようとしています。オブジェクトを構築するときは最初にその親コン​​ストラクターを呼び出し、破棄するときはその逆であることを私は知っています。

フィールド (A a;この場合) はどうですか? はいつ作成され、いつコンストラクターBを呼び出しますか? A初期化リストを定義していません。デフォルトのリストのようなものはありますか? そして、デフォルトのリストがない場合は? そして、破壊についての同じ質問。

4

6 に答える 6

79
  • 建設は常にベースから始まりますclass。複数の base classes がある場合は、一番左の base から構築が開始されます。(補足:継承がある場合は、virtual優先度が高くなります)。
  • 次に、メンバー フィールドが構築されます。宣言された順序で初期化されます
  • 最後に、classそれ自体が構築されます
  • デストラクタの順序はまったく逆です

初期化リストに関係なく、呼び出し順序は次のようになります。

  1. Baseclass Aのコンストラクタ
  2. class Baの(タイプ の)という名前のフィールドclass Aが構築されます
  3. Derivedclass Bのコンストラクタ
于 2011-09-24T13:28:28.337 に答える
24

仮想/多重継承 (かなり複雑になります) がないと仮定すると、ルールは単純です。

  1. オブジェクトメモリが割り当てられます
  2. 基本クラスのコンストラクターが実行され、ほとんどの派生クラスで終了します
  3. メンバーの初期化が実行されます
  4. オブジェクトはそのクラスの真のインスタンスになります
  5. コンストラクターコードが実行される

覚えておくべき重要なことの 1 つは、オブジェクトはコンストラクターの実行が開始された後にのみこのタイトルを取得するため、ステップ 4 まではまだそのクラスのインスタンスではないということです。つまり、メンバーのコンストラクター中に例外がスローされた場合、オブジェクトのデストラクターは実行されず、既に構築された部分 (メンバーや基本クラスなど) のみが破棄されます。これは、メンバーまたは基底クラスのコンストラクターでオブジェクトの仮想メンバー関数を呼び出す場合、呼び出される実装は派生実装ではなく基底実装になることも意味します。覚えておくべきもう 1 つの重要なことは、初期化リストにリストされているメンバーは、クラスで宣言されている順序で構築されるということです。

thisまた、コンストラクター コードの実行中にオブジェクトが既に最終クラスを取得している場合でも(たとえば、仮想ディスパッチに関して)、コンストラクターがその実行を完了しない限り、クラスのデストラクタは呼び出されないことに注意してください。コンストラクターが実行を完了した場合にのみ、オブジェクトインスタンスはインスタンスの中で実際のファーストクラスの市民になります...その時点までは、「インスタンスになりたい」だけです(正しいクラスがあるにもかかわらず)。

破壊はまったく逆の順序で行われます。最初にオブジェクト デストラクタが実行され、次にそのクラスが失われます (つまり、この時点からオブジェクトは基本オブジェクトと見なされます)。次に、すべてのメンバーが逆の宣言順序で破壊され、最後に基本クラスの破壊プロセスが行われます。最も抽象的な親まで実行されます。コンストラクタに関しては、オブジェクトの仮想メンバ関数をベースまたはメンバ デストラクタで (直接的または間接的に) 呼び出すと、実行される実装は親になります。これは、クラス デストラクタが完了したときにオブジェクトがクラス タイトルを失ったためです。

于 2011-09-24T13:50:08.920 に答える
3

基本クラスのコンストラクターは常に最初に実行されます。したがって、ステートメントを作成するとB b;、のコンストラクターがA最初に呼び出され、次にBクラスコンストラクターが呼び出されます。したがって、コンストラクターからの出力は次のように順番になります。

A() C-tor
A() C-tor
B() C-tor
于 2011-09-24T14:41:03.280 に答える
0

変更されたコードからの出力は次のとおりです。

A() C-tor
A() C-tor
B() C-tor
~B() D-tor
~A() D-tor
~A() D-tor
于 2011-09-24T13:50:27.230 に答える