親クラスの保護されたデータは子クラスでは使用できませんか?
質問
私は混乱しています:保護されたデータは、C ++の特定のクラスの子によって読み取り/書き込み可能だと思いました。
以下のスニペットは、MSコンパイラでコンパイルできません
class A
{
protected:
int data;
};
class B : public A
{
public:
B(A &a)
{
data = a.data;
}
};
int main()
{
A a;
B b = a;
return 0;
}
エラーメッセージ:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.30729.01 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
demoFail.cpp
demoFail.cpp(12) : error C2248: 'A::data' : cannot access protected member declared in class 'A'
demoFail.cpp(4) : see declaration of 'A::data'
demoFail.cpp(2) : see declaration of 'A'
間違っているのは何ですか?
解決
TC ++ PLによると、ページ404:
派生クラスは基本クラスにアクセスできます’独自の型のオブジェクトのみの保護されたメンバー....これにより、1つの派生クラスが他の派生クラスに属するデータを破損した場合に発生する微妙なエラーが防止されます。
もちろん、これをケースに合わせて修正する簡単な方法を次に示します。
class A
{
protected:
int data;
};
class B : public A
{
public:
B(const A &a)
: A(a)
{
}
};
int main()
{
A a;
B b = a;
return 0;
}
他のヒント
C ++標準では、 11.5 / 1
フレンドまたは派生クラスのメンバー関数が、保護された非静的メンバー関数または基本クラスの保護された非静的データメンバーを参照する場合、11節で前述したものに加えて、アクセスチェックが適用されます。メンバー(5.3.1)の場合、アクセスは、派生クラス自体(またはそのクラスから派生したクラス)へのポインター、参照、またはオブジェクトを介する必要があります(5.2.5)。アクセスがメンバーへのポインターを形成する場合、ネストされた名前指定子は、派生クラス(またはそのクラスから派生したクラス)に名前を付けるものとします。
他の人( B
のコンストラクタはプライベートです)が先に言及したものを修正することに加えて、rlbondの方法でうまくいくと思います。ただし、標準の上記の段落の直接的な結果は、当然のことながら型システムの穴であると思われるメンバーポインターを使用して次のことが可能であることです
class B : public A {
public:
B(A &a){
int A::*dataptr = &B::data;
data = a.*dataptr;
}
};
もちろん、このコードは推奨されていませんが、本当に必要な場合はアクセスできることを示しています(この方法がの印刷に使用されているのを見ました) std :: stack
、 std :: queue
、 std :: priority_queue
の保護されたコンテナメンバー c
)
B
コンストラクタ内の A
オブジェクトをコピーしないでください。意図は、 A
のメンバーの初期化を独自のコンストラクターに任せることです:
struct A {
A( const A& a ): data( a.data ) {}
protected: int data;
};
struct B : public A {
B( const A& a ): A( a ) {}
};
Bのコンストラクターはプライベートです。クラスで何も指定しない場合、デフォルトの修飾子はprivateです(構造体の場合はpublicです)。したがって、この例の問題は、Bを構築できないことです。コンストラクタBにpublicを追加すると、次の問題が発生します。
Bには、この場合のように別のAではなく、派生元のAの部分を変更する権利があります。
次のことができます:
class A
{
public:
A()
: data(0)
{
}
A(A &a)
{
data = a.data;
}
protected:
int data;
};
class B : public A
{
public:
B(A &a)
: A(a)
{
}
};
int main()
{
A a;
B b = a;
return 0;
}