c ++:初期化子リスト順のコンストラクター

CluelessButCurious

次のコードがどのように実行されるかについて、いくつか質問があります

using namespace std;
class A
{
    int i;
public:
    A() { i = 7; cout << 1 << f() << i; }
    A(int i) :i(i) { cout << 1 << f() << i; }
    char f() { return 'A'; }
};
class B : public virtual A
{
    int i;
public:
    B(int i) : A(i), i(++i) { cout << 2 << i; }
    virtual char f() { return 'B'; }
};
class C : public virtual A {
public:
    C(int i) : A(i) { cout << 3 << i; }
    virtual char f() { return 'C'; }
};
class D :public A {
public:
    D(int i) { cout << 4 << i; }
    virtual char f() { return 'D'; }
};
class E : public B, public C, public D {
public:
    E() : B(2), C(3), D(4) { cout << 5; }
    virtual char f() { return 'E'; }
};
int main()
{
    E e;
    return 0;
}

したがって、出力は「1A723331A7445」になります。

  • まず、次のことを考えて正しいことを再確認したいと思います。Aに入力されているiが初期化されていないため、「1A2」ではなく「1A7」を出力することから始まります。私はこれを正しく理解していますか?
  • 次に、C(3)が「1A7」を出力する前に「33」を出力するのはなぜか疑問に思いました。
StoryTeller-Unslander Monica

そうです、あなたが本当にめちゃくちゃなタイプ階層を作成したと言うことから始めましょう。初期化の順序を理解しようとした場合、この例は混乱を招く可能性があります。

とにかく、物事を明確にするために、私はあなたのコードを変更し、/各c'torprintステートメントの最後にスラッシュ文字を追加しましたしたがって、行のどの部分が各c'torに属しているかをより簡単に識別できます。これにより、次の出力が得られます。

1A7 / 23/33 / 1A7 / 44/5

初期化の順序に入る前に、指定したすべての仮想関数が動的にディスパッチされないことを知っておく必要があります。C'tor本体の仮想関数は静的にバインドされます。したがって、私たちの意図と目的のために、コードで呼び出される仮想関数は実際にはありません。

さて、C ++標準を引用すると、これは初期化順序が決定される方法です([class.base.init] / 13):

非委任コンストラクターでは、初期化は次の順序で進行します。

  • まず、最も派生したクラスのコンストラクターの場合のみ、仮想基本クラスは、基本クラスの有向非巡回グラフの深さ優先の左から右へのトラバーサルに表示される順序で初期化されます。ここで、「左から右」 」は、派生クラスbase-specifier-list内の基本クラスの出現順序です

  • 次に、直接基本クラスは、base-specifier-listに表示される宣言の順序で初期化されますmem-initializersの順序に関係なく)。

  • 次に、非静的データメンバーは、クラス定義で宣言された順序で初期化されます(ここでも、mem-initializersの順序に関係なく)。

  • 最後に、コンストラクター本体の複合ステートメントが実行されます。

それでは、初期化を分解してみましょう。

1)仮想Aあなたがのリスト初期化子メンバーでそれを指定しなかったため、サブオブジェクトがデフォルトの構築、でE()、それは実行A()のために共有されているオブジェクトのためにBC、そしてプリント1A7/

2)ここで、のc'torBが呼び出され、で実行さB(int i)i = 2ます。に設定さB::i3、c'tor本体が印刷され23/ます。

3)Cを呼び出すことによって構築されるC(int i)i = 3これは印刷し33/ます。

4)次に、を作成しDます。あなたが呼ぶそうD(int i)i = 4非仮想からD継承するためA今すぐA構築が必要な別個のサブオブジェクトがあります

  1. メンバー初期化子リストでパラメーターを指定しなかったためA、デフォルトで作成されます。これは印刷し1A7/ます。

  2. これで、本体がD(int i)実行され、印刷され44/ます。

5)最後に、の本体E()が呼び出され、印刷され5ます。

この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。

侵害の場合は、連絡してください[email protected]

編集
0

コメントを追加

0

関連記事

分類Dev

C ++コンストラクタ初期化子リストのテンプレート配列の初期化

分類Dev

C ++:代入なしのコンストラクタ初期化子リストの代替?

分類Dev

C ++ 11の統一された初期化:初期化子リストと複数パラメーターコンストラクターの間のあいまいさ?

分類Dev

C ++ 11メンバー初期化子リストとクラス内初期化子?

分類Dev

C ++は、他のパラメーターを持つコンストラクターの初期化子リストを取得します

分類Dev

C ++の初期化子リストとクラスの初期化。引数なしのコンストラクターがありますが、初期化リストを使用する必要がありますか?

分類Dev

C ++の初期化子リストとクラスの初期化。引数なしのコンストラクターがありますが、初期化リストを使用する必要がありますか?

分類Dev

複雑な割り当てを持つc ++コンストラクタ初期化子リスト

分類Dev

C ++コンストラクタ初期化子リストで非組み込み型の配列を初期化するにはどうすればよいですか?

分類Dev

'using std :: foo'ディレクティブをコンストラクター初期化子リストにローカルに適用します(C ++)

分類Dev

const型のコンストラクタ初期化子のC ++正しい入力検証

分類Dev

C ++入門書には、「= default」コンストラクターに初期化子リストを使用できると書かれています

分類Dev

C ++のクラスコンストラクターでのリストの初期化

分類Dev

C#オブジェクト初期化子-コンストラクター呼び出しの括弧を含めますか?

分類Dev

C ++コンストラクタ初期化リストのC構造体コピー

分類Dev

C ++:初期化されたリストを持つデフォルトのコンストラクター

分類Dev

C ++は、初期化リストの外部で親コンストラクターを明示的に呼び出します

分類Dev

c ++初期化テンプレートクラスコンストラクター

分類Dev

可変個引数コンストラクターに初期化リストの初期化リストを理解させるC ++ 11

分類Dev

C ++でのデストラクタとコンストラクタの順序

分類Dev

コンストラクターc ++の異なるクラスへのポインターの初期化

分類Dev

C ++で、初期化子リストで基本クラスのテンプレート引数を繰り返す必要があるのはなぜですか?

分類Dev

C ++フィールドの直接初期化とデフォルトコンストラクターの初期化リスト

分類Dev

コンストラクターc ++で属性を初期化する際の問題

分類Dev

C#コンストラクターでの初期化が機能しない

分類Dev

C ++のクラスコンストラクタでのメモリリーク

分類Dev

仮想継承中のC ++コンストラクターの順序

分類Dev

コンストラクター(C ++)でのプライベートメンバーの初期化の違い

分類Dev

C ++:ネストされた構造体のフラット初期化子リスト?

Related 関連記事

  1. 1

    C ++コンストラクタ初期化子リストのテンプレート配列の初期化

  2. 2

    C ++:代入なしのコンストラクタ初期化子リストの代替?

  3. 3

    C ++ 11の統一された初期化:初期化子リストと複数パラメーターコンストラクターの間のあいまいさ?

  4. 4

    C ++ 11メンバー初期化子リストとクラス内初期化子?

  5. 5

    C ++は、他のパラメーターを持つコンストラクターの初期化子リストを取得します

  6. 6

    C ++の初期化子リストとクラスの初期化。引数なしのコンストラクターがありますが、初期化リストを使用する必要がありますか?

  7. 7

    C ++の初期化子リストとクラスの初期化。引数なしのコンストラクターがありますが、初期化リストを使用する必要がありますか?

  8. 8

    複雑な割り当てを持つc ++コンストラクタ初期化子リスト

  9. 9

    C ++コンストラクタ初期化子リストで非組み込み型の配列を初期化するにはどうすればよいですか?

  10. 10

    'using std :: foo'ディレクティブをコンストラクター初期化子リストにローカルに適用します(C ++)

  11. 11

    const型のコンストラクタ初期化子のC ++正しい入力検証

  12. 12

    C ++入門書には、「= default」コンストラクターに初期化子リストを使用できると書かれています

  13. 13

    C ++のクラスコンストラクターでのリストの初期化

  14. 14

    C#オブジェクト初期化子-コンストラクター呼び出しの括弧を含めますか?

  15. 15

    C ++コンストラクタ初期化リストのC構造体コピー

  16. 16

    C ++:初期化されたリストを持つデフォルトのコンストラクター

  17. 17

    C ++は、初期化リストの外部で親コンストラクターを明示的に呼び出します

  18. 18

    c ++初期化テンプレートクラスコンストラクター

  19. 19

    可変個引数コンストラクターに初期化リストの初期化リストを理解させるC ++ 11

  20. 20

    C ++でのデストラクタとコンストラクタの順序

  21. 21

    コンストラクターc ++の異なるクラスへのポインターの初期化

  22. 22

    C ++で、初期化子リストで基本クラスのテンプレート引数を繰り返す必要があるのはなぜですか?

  23. 23

    C ++フィールドの直接初期化とデフォルトコンストラクターの初期化リスト

  24. 24

    コンストラクターc ++で属性を初期化する際の問題

  25. 25

    C#コンストラクターでの初期化が機能しない

  26. 26

    C ++のクラスコンストラクタでのメモリリーク

  27. 27

    仮想継承中のC ++コンストラクターの順序

  28. 28

    コンストラクター(C ++)でのプライベートメンバーの初期化の違い

  29. 29

    C ++:ネストされた構造体のフラット初期化子リスト?

ホットタグ

アーカイブ