7

この回答は、それが機能するはずであることを示唆しているように見えるので、なぜ私の例ではコンパイラエラーが発生するのですか:

class Class1
{
protected:
    long m_memberVar;
};

class SubClass1: public Class1
{
public:
    void PrintMember(Class1 memberToPrintFrom)
    {
        Console::Write("{0}", memberToPrintFrom.m_memberVar); // <-- Compiler error: error C2248: 'BaseClassMemberAccess::Class1::m_memberVar' : cannot access protected member declared in class 'BaseClassMemberAccess::Class1'
    }
};

[編集] - Need4Sleep の提案でサブクラスを公開継承に変更しましたが、違いはありません。

4

3 に答える 3

14

この回答ではpublic、コードで継承を使用したと仮定します(これは質問にはありませんでした)。


[C++11: 11.2/1]: publicクラスがアクセス指定子を使用して別のクラスの基本クラスとして宣言されている場合 (条項 10)public、基本クラスのメンバーpublicは派生クラスのメンバーとしてアクセス可能であり、基本クラスのメンバーは派生クラスのメンバーprotectedとしてアクセス可能protectedです。 . protectedアクセス指定子を使用してクラスが別のクラスの基底クラスとして宣言されている場合、基底クラスのpublicおよびメンバーは、派生クラスのメンバーprotectedとしてアクセスできます。protectedアクセス指定子を使用してクラスが別のクラスの基底クラスとして宣言されている場合、基底クラスprivateの public およびメンバーは、派生クラスのメンバーprotectedとしてアクセスできます。private

これは、同じオブジェクトのメンバーにアクセスしている場合をカバーしています。

ただし、別のオブジェクトのメンバーprotectedにアクセスするには、同じ型またはより派生した型の定義内に配置する必要があるというのは、メンバー アクセスのちょっとした好奇心です。あなたの場合、それはより少ない派生型(つまり、ベース)にあります:protected

[C++11: 11.4/1]:非静的データ メンバーまたは非静的メンバー関数がその名前付けクラスの保護されたメンバーである場合、条項 11 で前述したものを超える追加のアクセス チェックが適用されます (11.2)。前述のように、保護されたメンバーへのアクセスは、参照は、一部のクラスのフレンドまたはメンバーで発生しCます。アクセスがメンバーへのポインターを形成することである場合 (5.3.1)、nested-name-specifierCはまたは から派生したクラスを示すものとしCます。他のすべてのアクセスには、(おそらく暗黙の) オブジェクト式 (5.2.5) が含まれます。この場合、オブジェクト式のクラスはCまたは から派生したクラスでなければなりませんC

つまり、Class1メンバー関数内からこのコードを実行する必要があります。

Bjarne は、彼の著書The C++ Programming Language (Sp. Ed.)の 404 ページでこれについて言及しています。

派生クラスは、独自の型のオブジェクトに対してのみ、基本クラスの保護されたメンバーにアクセスできます [...] これにより、1 つの派生クラスが他の派生クラスに属するデータを破損したときに発生する微妙なエラーを防ぐことができます。

于 2012-12-05T12:32:14.513 に答える
2

派生クラスは、基底クラスの保護されたメンバーに、それ自体 (this) または同じクラスの別のオブジェクトを介してのみアクセスできますが、基底クラスを介して一般的にアクセスすることはできません。それがアクセスであり、その目的は、メンバーの使用がクラスの実装の詳細に制限されていると見なされることです。クラスは基本クラスを扱っているため、この特定のケースではメンバーの意味を知りません.

アクセスを取得するために使用できる回避策があります。これは、基本クラスで保護されたゲッターとセッターを提供することであり、多くの場合静的であり、それをフェッチまたは設定します。

class Class1
{
     protected:
       long m_memberVar; // could even be private

       static long getMemberVar( Class1 const& inst )
       {
          return inst.m_memberVar;
       }

       static long setMemberVar( Class1 & inst, long val )
       {
          inst.m_memberVar = val;
       }

};

また、派生クラス (一般クラスではない) で getter メソッドと setter メソッドを使用できるようになりました。

于 2012-12-05T12:36:37.253 に答える