これがコードであり、「不正なメンバーの初期化:'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
}
これがコードであり、「不正なメンバーの初期化:'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
}
派生クラスのコンストラクターが呼び出されるまでに、基本クラスはすでに構築されている必要があります。ですから、もう手遅れです。なぜこのようにする必要があるのかを理解するには、次のことを考慮してください。
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
に再構築できますか?
ここで何が起こっているかについてのより完全な説明については、この回答を参照してください。A::a
基本的に、のイニシャライザで初期化することはできませんB
。これは、標準に従って形式が正しくないためです。
もう1つの重要な情報-クラスがコンストラクター初期化リストを介してメンバーオブジェクトを初期化しない場合、そのメンバーのデフォルトコンストラクターは、基本クラスコンストラクターの最初のステートメントが実行される前に呼び出されることに注意してください。イニシャライザーを使用する場合、実際に行っているのは、デフォルトのコンストラクターの代わりに使用するコンストラクターを指定することです。
明らかに、派生クラスを構築しているときは、親クラスメンバーがすでに構築されているため、ベースメンバーを再構築することはできません。これは、派生クラス初期化リストに含めることで、この例で実行しようとしていることです。
余談ですが、派生クラスでA :: aの値を特定の値に設定できるようにするだけの場合は、代わりに次のコードを使用してください。
B::B()
{
a = 10;
}
基本クラスは独自の方法で物事を初期化したい場合があるためです。適切な方法は、初期化子リスト内の基本コンストラクターを呼び出し、基本ctorにそれ自体を初期化させることです。