2009-09-12 5 views
11

私は混乱しています。私は、保護されたデータが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' 

は私が間違って何をしているのですか?

答えて

10

をTC++ PL、PG 404によると:基本クラスにアクセスすることができ、派生クラスのみ、独自の型のオブジェクトのメンバーを保護

....これにより、ある派生クラスが他の派生クラスに属するデータを壊した場合に発生する微妙なエラーを防ぎます。もちろん

は、ここにあなたのケースのために、この問題を解決する簡単な方法です:

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; 
} 
+0

Umph。正確に言えば、このケースは問題を示すためのダミーケースです。私は実際に渡されるデータのかなり集中的な読書をしたいと思っていました。 –

+0

いずれにしても、このAオブジェクトまたは別のBオブジェクトのA部分の保護されたデータだけで動き回ることができます。 AインスタンスまたはCインスタンスがAから派生している場合、BにはそれらのAsに対する特別な権利はありません。このアドバイスを受けられない場合(このBを、このBの基本部分にコピーしてコピーして、これにアクセスしてください)、より大きな画像が必要な設計上の問題が発生する可能性があります。回答。 – UncleBens

+0

@rlbond:就寝時のストライキ後のコーディング。これは私の問題を解決しました。ありがとう。 :) –

0

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; 
} 
+0

私が考えたものだが、それは問題ではないこと。 – rlbond

+0

@jde:実際はタイプミスです。 Bのコンストラクタをpublicにすると、同じエラーが発生します。 –

+0

@Paul、質問に偶発的な誤植を修正してください。したがって、さらなる回答は同じ解決策を提案しません:) –

2
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; 
    } 
}; 

もちろん、おそらく型システムにおける孔であるメンバポインタを使用して可能であることで、このコードは推奨されません(その保護された容器部材cにアクセスすることによって、私はstd::stackをプリントアウトするために使用されているこの方法を見てきました、std::queuestd::priority_queue)を行うが、あなたが本当にする必要がある場合、あなたアクセスそれができることを示してします

+0

こんにちはヨハネス・シャウブ - litbあなたがのstd ::スタックまたはSTDで保護部材Cにアクセスする方法を私に示してくださいすることができ::キュー は、私はそれを へのアクセスに問題があり、それは私にエラーを与えましたC2248: 'std :: stack <_Ty> :: c':クラス 'std :: stackで宣言された保護されたメンバーにアクセスできません:: <_Ty>' ありがとう –

1

あなただけのは、をコピーしないでください。AオブジェクトをコンストラクタBにコピーします。意図は、それ自身のコンストラクタにAのメンバーの初期化を残すことである:

struct A { 
    A(const A& a): data(a.data) {} 
    protected: int data; 
}; 

struct B : public A { 
    B(const A& a): A(a) {} 
}; 
関連する問題