5

基本的なライブラリ カタログ システムを模倣する一連のコードがあります。items という名前の基本クラスがあり、一般的な id、title、および year 変数が定義されており、他の 3 つの派生クラス (DVD、Book、および CD) が定義されています。

ベース 【アイテム】

派生[DVD、本、CD]。

プログラムは実行されますが、次の警告が表示されます。これらを修正する方法がわかりません。

>"C:\Program Files\gcc\bin/g++" -Os -mconsole -g -Wall -Wshadow -fno-common mainA4.cpp -o mainA4.exe
mainA4.cpp:5 からインクルードされたファイル:
a4.h: コンストラクター「DVD::DVD(int, std::string, int, std::string)」:
a4.h:28: 警告: `DVD::director' は後で初期化されます
a4.h:32: 警告: ベース `Items'
a4.h:32: 警告: ここで初期化すると
a4.h: コンストラクタ `Book::Book(int, std::string, int, std::string, int)':
a4.h:48: 警告: `Book::numPages' は後で初期化されます
a4.h:52: 警告: ベース `Items'
a4.h:52: 警告: ここで初期化すると
a4.h: コンストラクター `CD::CD(int, std::string, int, std::string, int)':
a4.h:66: 警告: `CD::numSongs' は後で初期化されます
a4.h:70: 警告: ベース `Items'
a4.h:70: 警告: ここで初期化すると
>終了コード: 0
4

3 に答える 3

28

クラスでメンバー変数を宣言すると、宣言した順序で初期化されます。ただし、コンストラクターの初期化子リストでは、それらを任意の順序で記述できます。例えば、

struct foo {
   int a;
   int b;

   foo(): b(5), a(3) {}
};

aは、次に を構築bしますが、それらを別の順序で初期化しているように見えます。

不正なコードを記述してしまう可能性があるため、コンパイラは警告を発行します。例えば、

struct foo {
    int a;
    int b;

    foo(): b(5), a(b) {}
};

の値はa未定義になります。

于 2010-05-02T04:44:32.960 に答える
6

コンストラクターとメンバーの初期化リストを確認する必要があります。コードを見ずに判断するのは難しいですが、何が起こっているかというと、次のようなコードがあるということです:-

class my_class : public base1, public base2
{
    public:
        my_class();

    private:
        member1 member1_;
        member2 member2_;
}

my_class::my_class() 
    : member2_(...)
    , member1_(...)
    , base2_(...)
    , base1_(...)
{ }

これにより、同様の警告が生成されます。その理由は、C++ では、コンストラクターは常に基本クラス リストに示されている順序 (base1 の後に base2) で基本クラスを構築し、クラス定義の上から下にメンバー変数を構築するためです。これは、メンバー初期化リストで指定した順序に関係なく行われます。この順序は無視されますが、一部のコンパイラ (自分のものを含む) と一致しない場合は、警告が表示されます。

ちなみにこれを行う理由は、C++ にはデストラクタがコンストラクタの逆の順序で呼び出されるという厳密な要件があるためです。そのため、メンバーの初期化リストの順序で処理を行う場合、どのコンストラクタが持っていたかを何とか「覚えておく」必要があります。デストラクタを正しい順序で呼び出すことができるように呼び出されました。これは行いませんが、代わりに常に同じ順序を使用します。

于 2010-05-02T04:49:13.317 に答える
3

コンストラクターでクラス メンバーを初期化するときは、宣言されているのと同じ順序で初期化します。例えば:

class Foo {
  public:
    int a;
    int b;
    Foo() : a(0), b(0) {}
};

コンストラクターでは、とFoo()の順序を切り替えると、警告が表示されます。同じことが基本クラスの初期化にも当てはまります (そのコンストラクターが明示的に呼び出される場合は、データ メンバー初期化子の前に呼び出す必要があります)。ab

于 2010-05-02T04:45:12.853 に答える