web-dev-qa-db-ja.com

アクセス指定子とは何ですか?プライベート、保護またはパブリックで継承する必要がありますか?

継承に関するアクセス修飾子の意味について混乱しています。 privateprotected、およびpublicキーワードを含む継承の違いは何ですか?

43
Sista

アクセス指定子とは何ですか?

3 access specifiers C++のクラス/構造体/ユニオンの場合。これらのアクセス指定子は、クラスのメンバーにアクセスする方法を定義します。もちろん、クラスのメンバーはそのクラス内でアクセスできます(同じクラスのメンバー関数内)。アクセス指定子のタイプに進むと、次のとおりです。

Public-Publicとして宣言されたメンバーは、クラスのオブジェクトを通じてクラスの外部からアクセスできます。

Protected-Protectedとして宣言されたメンバーは、クラスの外部からアクセスできます[〜#〜] but [〜#〜 ]派生クラスのみ。

Private-これらのメンバーは、クラス内からのみアクセスできます。外部アクセスは許可されていません。

ソースコードの例:

class MyClass
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

int main()
{
    MyClass obj;
    obj.a = 10;     //Allowed
    obj.b = 20;     //Not Allowed, gives compiler error
    obj.c = 30;     //Not Allowed, gives compiler error
}

継承およびアクセス指定子

C++の継承は、次のいずれかのタイプになります。

  • Private継承
  • Public継承
  • Protected inheritance

これらのそれぞれに関するメンバーアクセスルールは次のとおりです。

クラスの最初で最も重要なルールPrivateメンバーは、同じクラスのメンバー以外のどこからもアクセスできません。

公開継承:

基本クラスのすべてのPublicメンバーは、派生クラス&のPublicメンバーになります&
基本クラスのすべてのProtectedメンバーは、派生クラスのProtectedメンバーになります。

つまり、メンバーのアクセスに変更はありません。前に説明したアクセスルールは、さらにこれらのメンバーに適用されます。

コード例:

Class Base
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

class Derived:public Base
{
    void doSomething()
    {
        a = 10;  //Allowed 
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Allowed
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error

}

プライベート継承:

基本クラスのPublicメンバーはすべて、派生クラスのPrivateメンバーになります&
基本クラスのすべてのProtectedメンバーは、派生クラスのPrivateメンバーになります。

コード例:

Class Base
{
    public:
      int a;
    protected:
      int b;
    private:
      int c;
};

class Derived:private Base   //Not mentioning private is OK because for classes it  defaults to private 
{
    void doSomething()
    {
        a = 10;  //Allowed 
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

class Derived2:public Derived
{
    void doSomethingMore()
    {
        a = 10;  //Not Allowed, Compiler Error, a is private member of Derived now
        b = 20;  //Not Allowed, Compiler Error, b is private member of Derived now
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Not Allowed, Compiler Error
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error

}

保護された継承:

基本クラスのすべてのPublicメンバーは、派生クラス&のProtectedメンバーになります&
基本クラスのすべてのProtectedメンバーは、派生クラスのProtectedメンバーになります。

コード例:

Class Base
{
    public:
        int a;
    protected:
        int b;
    private:
        int c;
};

class Derived:protected Base  
{
    void doSomething()
    {
        a = 10;  //Allowed 
        b = 20;  //Allowed
        c = 30;  //Not Allowed, Compiler Error
    }
};

class Derived2:public Derived
{
    void doSomethingMore()
    {
        a = 10;  //Allowed, a is protected member inside Derived & Derived2 is public derivation from Derived, a is now protected member of Derived2
        b = 20;  //Allowed, b is protected member inside Derived & Derived2 is public derivation from Derived, b is now protected member of Derived2
        c = 30;  //Not Allowed, Compiler Error
    }
};

int main()
{
    Derived obj;
    obj.a = 10;  //Not Allowed, Compiler Error
    obj.b = 20;  //Not Allowed, Compiler Error
    obj.c = 30;  //Not Allowed, Compiler Error
}

同じアクセスルールが継承階層の下のクラスとメンバーに適用されることに注意してください。


注意すべき重要な点:

-アクセス仕様はオブジェクトごとではなくクラスごとです

アクセス仕様C++は、オブジェクトごとではなく、クラスごとに機能することに注意してください。
これの良い例は、コピーコンストラクターまたはコピー割り当て演算子関数で、渡されるオブジェクトのすべてのメンバーにアクセスできることです。

-派生クラスは、自身の基本クラスのメンバーにのみアクセスできます

次のコード例を考慮してください:

class Myclass
{ 
    protected: 
       int x; 
}; 

class derived : public Myclass
{
    public: 
        void f( Myclass& obj ) 
        { 
            obj.x = 5; 
        } 
};

int main()
{
    return 0;
}

コンパイルエラーが発生します。

prog.cpp:4:エラー:「int Myclass :: x」は保護されています

派生クラスは、その独自の基本クラスのメンバーにのみアクセスできるためです。ここで渡されるオブジェクトobjは、アクセスされるderivedクラス関数とはまったく関係がなく、まったく異なるオブジェクトであり、したがってderivedメンバー関数であることに注意してください。メンバーにアクセスできません。


friendとは何ですか? friendはアクセス仕様ルールにどのように影響しますか?

関数またはクラスを別のクラスのfriendとして宣言できます。その場合、アクセス仕様ルールはfriendedクラス/関数に適用されません。クラスまたは関数は、その特定のクラスのすべてのメンバーにアクセスできます。

だから、friendsはカプセル化を壊しますか?

いいえ、そうではありませんが、逆にカプセル化を強化します!

friendshipは、2つのエンティティ間の意図的な強い結合を示すために使用されます。
2つのエンティティ間に特別な関係があり、一方が他のprivateまたはprotectedメンバーにアクセスする必要があるが、必要ない場合everyonepublicアクセス指定子を使用してアクセスするには、friendshipを使用する必要があります。

150
Alok Save

Effective C++のScott Meyersからの説明は、それらをいつ使用するかを理解するのに役立つかもしれません。

パブリック継承は「is-a関係」をモデル化する必要がありますが、プライベート継承は「is-implemented-in-terms-of」に使用する必要があります。そのため、スーパークラスのインターフェースに従う必要はなく、再利用するだけです。実装。

5
Ivan Vergiliev