2

これがコードであり、「不正なメンバーの初期化:'a'はベースまたはメンバーではありません」というエラーがあります。エラー情報の意味は何ですか。その理由は何ですか。

class A{
public:
int a;
};
class B:public A{

public:
B();
};

B::B():a(10){    // put  "a(10)" into the constructor body is right

}
4

4 に答える 4

8

派生クラスのコンストラクターが呼び出されるまでに、基本クラスはすでに構築されている必要があります。ですから、もう手遅れです。なぜこのようにする必要があるのか​​を理解するには、次のことを考慮してください。

class Base
{
    public:
    int i;
    Base(int q) : i(q) { ; }
};

class Middle : public Base
{
    public:
    Middle() : Base(2) { printf("i=%d\n", i); }
};

class Derived : public Middle
{
    public:
    Derived() : i(3) { ; }
}

さて、考えてみてください。コンストラクターは、コンストラクターMiddleの前に実行する必要がありDerivedます。そして、Middleコンストラクターはそれが2であることを保証しiます。では、コンストラクターは後で別の値でそれをどのようDerivedに再構築できますか?

于 2012-08-07T02:44:01.633 に答える
2

ここで何が起こっているかについてのより完全な説明については、この回答を参照してください。A::a基本的に、のイニシャライザで初期化することはできませんB。これは、標準に従って形式が正しくないためです。

于 2012-08-07T02:37:16.940 に答える
1

もう1つの重要な情報-クラスがコンストラクター初期化リストを介してメンバーオブジェクトを初期化しない場合、そのメンバーのデフォルトコンストラクターは、基本クラスコンストラクターの最初のステートメントが実行される前に呼び出されることに注意してください。イニシャライザーを使用する場合、実際に行っているのは、デフォルトのコンストラクターの代わりに使用するコンストラクターを指定することです。

明らかに、派生クラスを構築しているときは、親クラスメンバーがすでに構築されているため、ベースメンバーを再構築することはできません。これは、派生クラス初期化リストに含めることで、この例で実行しようとしていることです。

余談ですが、派生クラスでA :: aの値を特定の値に設定できるようにするだけの場合は、代わりに次のコードを使用してください。

B::B()
{
    a = 10;
}
于 2012-08-07T03:28:39.303 に答える
0

基本クラスは独自の方法で物事を初期化したい場合があるためです。適切な方法は、初期化子リスト内の基本コンストラクターを呼び出し、基本ctorにそれ自体を初期化させることです。

于 2012-08-07T02:35:48.250 に答える