質問

違いは何ですか public, private, 、 そして protected C++での継承?SO で見つけた質問はすべて、特定のケースを扱っています。

役に立ちましたか?

解決

その質問に答えるために、まずメンバーのアクセサーについて私自身の言葉で説明したいと思います。すでにご存知の場合は、見出し「次へ:」までスキップしてください。

私が知っているアクセサーは 3 つあります。 public, protected そして private.

させて:

class Base {
    public:
        int publicMember;
    protected:
        int protectedMember;
    private:
        int privateMember;
};
  • 意識していることすべて Base それも承知している Base 含まれています publicMember.
  • そのことを知っているのは子供たち(そしてその子供たち)だけです Base 含まれています protectedMember.
  • 誰もいない Base 知っています privateMember.

「認識している」とは、「の存在を認識し、したがってアクセスできる」ことを意味します。

次:

パブリック、プライベート、保護された継承でも同じことが起こります。クラスを考えてみましょう Base そしてクラス Child から継承するもの Base.

  • 相続があった場合、 public, 、知っていることすべて Base そして Child それも承知している Child から継承します Base.
  • 相続があった場合、 protected, 、 のみ Child, とその子は、以下から継承していることを認識しています。 Base.
  • 相続があった場合、 private, 、他の誰も Child 継承を認識しています。

他のヒント

class A 
{
public:
    int x;
protected:
    int y;
private:
    int z;
};

class B : public A
{
    // x is public
    // y is protected
    // z is not accessible from B
};

class C : protected A
{
    // x is protected
    // y is protected
    // z is not accessible from C
};

class D : private A    // 'private' is default for classes
{
    // x is private
    // y is private
    // z is not accessible from D
};

重要:クラスB、CおよびDはすべて、YおよびZ、変数xを含みます。これは、アクセスの問題だけです。

保護および民間の継承の使用について、あなたはここにのを読み取ることができます。

継承の可視性を制限すると、コードはあるクラスが別のクラスを継承していることを認識できなくなります。派生型からベース型への暗黙的な変換は機能しません。 static_cast ベースから派生へも機能しません。

クラスのメンバー/フレンドのみがプライベート継承を参照でき、メンバー/フレンドおよび派生クラスのみが保護された継承を参照できます。

公共 継承

  1. IS-A の継承。ボタンはウィンドウであり、ウィンドウが必要な場所にはどこでもボタンを渡すことができます。

    class button : public window { };
    

保護された 継承

  1. という観点から実装され保護されています。まれに役に立ちます。で使われる boost::compressed_pair 空のクラスから派生し、空の基本クラスの最適化を使用してメモリを節約します (以下の例では、その点を維持するためにテンプレートを使用していません)。

    struct empty_pair_impl : protected empty_class_1 
    { non_empty_class_2 second; };
    
    struct pair : private empty_pair_impl {
      non_empty_class_2 &second() {
        return this->second;
      }
    
      empty_class_1 &first() {
        return *this; // notice we return *this!
      }
    };
    

プライベート 継承

  1. という観点から実装されています。基本クラスは派生クラスを実装する目的でのみ使用されます。サイズが重要な場合に、特性で使用すると便利です (関数のみを含む空の特性では、空の基本クラスの最適化が使用されます)。頻繁 封じ込め ただし、それはより良い解決策です。文字列のサイズは重要であるため、ここでよく見られる使用法です。

    template<typename StorageModel>
    struct string : private StorageModel {
    public:
      void realloc() {
        // uses inherited function
        StorageModel::realloc();
      }
    };
    

公共 メンバー

  1. 集計

    class pair {
    public:
      First first;
      Second second;
    };
    
  2. アクセサ

    class window {
    public:
        int getWidth() const;
    };
    

保護された メンバー

  1. 派生クラスへの拡張アクセスの提供

    class stack {
    protected:
      vector<element> c;
    };
    
    class window {
    protected:
      void registerClass(window_descriptor w);
    };
    

プライベート メンバー

  1. 実装の詳細を保持する

    class window {
    private:
      int width;
    };
    

C スタイルのキャストでは、定義された安全な方法で派生クラスを保護された基本クラスまたはプライベート基本クラスにキャストしたり、その逆の方向にキャストしたりすることを意図的に許可していることに注意してください。コードが実装の詳細に依存する可能性があるため、これは絶対に避けるべきですが、必要に応じてこの手法を利用できます。

これは、基本クラスのパブリック メンバーが派生クラスからどのように公開されるかに関係します。

  • public -> 基本クラスの public メンバーは public になります (通常はデフォルト)
  • protected -> 基本クラスの public メンバーは保護されます
  • private -> 基本クラスの public メンバーは private になります

litb が指摘しているように、パブリック継承は、ほとんどのプログラミング言語で見られる伝統的な継承です。つまり、「IS-A」関係をモデル化します。プライベート継承は、知る限り C++ に特有のもので、「IMPLEMENTED IN TERMS OF」関係です。それがあなたがしたいことです 使用 派生クラスのパブリック インターフェイスですが、派生クラスのユーザーがそのインターフェイスにアクセスできるようにしたくありません。この場合、基本クラスを集約する必要がある、つまり、基本クラスをプライベート基本として持つ代わりに、基本クラスの機能を再利用するために派生のメンバーを作成する必要があると多くの人が主張しています。

これら 3 つのキーワードは、完全に異なるコンテキストでも使用され、 可視性継承モデル.

この表は、サブクラスが完全に定義されたときのコンポーネントへのアクセスを示す、コンポーネント宣言と継承モデルの可能な組み合わせをすべて集めたものです。

enter image description here

上の表は次のように解釈されます (最初の行を見てください)。

コンポーネントが 宣言された として 公共 そしてそのクラスは 遺伝性の として 公共 結果として アクセス公共.

例:

 class Super {
    public:      int p;
    private:     int q;
    protected:   int r;
 };

 class Sub : private Super {};

 class Subsub : public Sub {};

結果として得られる変数へのアクセス p, q, r クラスで サブサブなし.

もう一つの例:

class Super {
    private:     int x;
    protected:   int y;
    public:      int z;
 };
class Sub : protected Super {};

結果として得られる変数へのアクセス y, z クラスで サブ保護された そして変数の場合 xなし.

より詳細な例:

class Super {
private:
    int storage;
public:
    void put(int val) { storage = val;  }
    int  get(void)    { return storage; }
};
int main(void) {
    Super object;

    object.put(100);
    object.put(object.get());
    cout << object.get() << endl;
    return 0;
}

次に、サブクラスを定義しましょう。

class Sub : Super { };

int main(void) {
    Sub object;

    object.put(100);
    object.put(object.get());
    cout << object.get() << endl;
    return 0;
}

Sub という名前の定義済みクラス。これは、という名前のクラスのサブクラスです。 Super またはその Sub クラスはから派生します Super クラス。の Sub クラスは新しい変数も新しい関数も導入しません。の任意のオブジェクトを意味しますか? Sub クラスはその後のすべての特性を継承します。 Super クラスは実際には のコピーです Super クラスのオブジェクト?

いいえ. 。そうではありません。

次のコードをコンパイルすると、次のようなコンパイル エラーが発生します。 put そして get メソッドにはアクセスできません。なぜ?

可視性指定子を省略すると、コンパイラはいわゆる 私的継承. 。つまり、すべてが 公共 スーパークラスコンポーネントは次のようになります プライベート にアクセスすると、プライベート スーパークラス コンポーネントにはまったくアクセスできなくなります。したがって、サブクラス内で後者を使用することは許可されていないことを意味します。

以前に使用したアクセス ポリシーを保存したいことをコンパイラに通知する必要があります。

class Sub : public Super { };

誤解しないでください:それは、スーパークラスのプライベートコンポーネント(ストレージ変数など)がやや魔法のような方法で公共のコンポーネントに変わるという意味ではありません。 プライベート コンポーネントは残ります プライベート, 公共残ります 公共.

のオブジェクト Sub クラスは、 Super クラス。 "ほとんど" なぜなら、サブクラスであるという事実は、 クラスはスーパークラスのプライベート コンポーネントへのアクセスを失いました. 。のメンバー関数を書くことはできません。 Sub ストレージ変数を直接操作できるクラス。

これは非常に重大な制限です。回避策はありますか?

はい.

3 番目のアクセス レベルは次のように呼ばれます。 保護された. 。キーワード protected は、そのキーワードでマークされたコンポーネントが サブクラスのいずれかで使用される場合はパブリック クラスのように動作し、他の世界に対してはプライベート クラスのように見えます。. -- これは、パブリックに継承されたクラス (この例のスーパー クラスなど) にのみ当てはまります。 --

class Super {
protected:
    int storage;
public:
    void put(int val) { storage = val;  }
    int  get(void)    { return storage; }
};

class Sub : public Super {
public:
    void print(void) {cout << "storage = " << storage;}
};

int main(void) {
    Sub object;

    object.put(100);
    object.put(object.get() + 1);
    object.print();
    return 0;
}

サンプルコードにあるように、新しい機能が追加されています。 Sub クラスを作成すると、重要なことが 1 つ実行されます。 スーパークラスからストレージ変数にアクセスします。.

変数がプライベートとして宣言されている場合は不可能です。main 関数のスコープでは、変数はとにかく隠されたままなので、次のように記述すると、次のようになります。

object.storage = 0;

コンパイラは、それが error: 'int Super::storage' is protected.

最後に、最後のプログラムは次の出力を生成します。

storage = 101
Member in base class : Private   Protected   Public   

の継承タイプのオブジェクトは、のように継承された

Private            :   Inaccessible   Private     Private   
Protected          :   Inaccessible   Protected   Protected  
Public             :   Inaccessible   Protected   Public

1) 公的相続:

a.基本クラスのプライベート メンバーには、派生クラスではアクセスできません。

b.基本クラスの保護されたメンバーは派生クラスでも保護されたままになります。

c.基本クラスのパブリック メンバーは派生クラスでもパブリックのままです。

そのため、他のクラスは派生クラス オブジェクトを通じて Base クラスのパブリック メンバーを使用できます。

2) 保護された継承:

a.基本クラスのプライベート メンバーには、派生クラスではアクセスできません。

b.基本クラスの保護されたメンバーは派生クラスでも保護されたままになります。

c.Base クラスのパブリック メンバーも、派生クラスの保護されたメンバーになります。

したがって、他のクラスは、派生クラス オブジェクトを通じて Base クラスのパブリック メンバーを使用できません。ただし、Derived のサブクラスでは使用できます。

3) 私的相続:

a.基本クラスのプライベート メンバーには、派生クラスではアクセスできません。

b.基本クラスの保護されたパブリック メンバーは、派生クラスのプライベート メンバーになります。

したがって、Base クラスのメンバーは派生クラスではプライベートであるため、派生クラス オブジェクトを通じて他のクラスからアクセスすることはできません。したがって、派生クラスのサブクラスでさえそれらにアクセスできません。

公共継承モデルIS-関係。

class B {};
class D : public B {};

すべてのD Bです。

プライベート継承モデルIS-IMPLEMENTED-使用した関係(またはものは何でもそれが呼ばれています)。

class B {};
class D : private B {};

DのないBですが、すべてのDは、その実装にそのBを使用しています。プライベート継承は常に代わりに封じ込めを使用することによって除去することができます:

class B {};
class D {
  private: 
    B b_;
};

このDは、あまりにも、そのBを使用して、この場合には、b_を用いて実現することができます。封じ込めは継承よりもタイプ間の少ない密結合であるため、一般的には好まれるべきです。時には、代わりに民間の継承の封じ込めを使用すると、private継承ほど便利ではありません。多くの場合、それは怠けているためラメ言い訳です。

私は、誰もが継承モデルをprotected知っているとは思いません。少なくとも私はまだ説得力のある説明を見ていません。

あなたが別のクラスから継承する場合は、公的

は、誰もがあなたが継承しているとあなたは、基本クラスのポインタを通じて誰でもポリモーフィックに使用することができます知っています。

あなたがprotectedlyだけあなたの子供を継承する場合、クラスはポリモーフィックあなたを使用することができます。

あなたが個人的に継承している場合のみ、自分が親クラスのメソッドを実行することができるようになります。

基本的に、あなたの親クラスとの関係

についてのクラスの残りの部分は持っている知識を象徴

保護されたデータメンバーがあなたのクラスから継承するすべてのクラスによってアクセスすることができます。プライベートデータメンバは、しかし、ことはできません。我々は持っている次のことを言ってみましょう。

class MyClass {
    private:
        int myPrivateMember;    // lol
    protected:
        int myProtectedMember;
};

このクラスへのあなたの拡張機能の中から、参照this.myPrivateMemberは動作しません。しかし、this.myProtectedMemberはなります。我々はmyObjと呼ばれるこのクラスのインスタンス化を持っている場合は、myObj.myProtectedMemberは動作しませんので、それはプライベートなデータメンバーと機能が似ているので、値はまだ、カプセル化されます。

Accessors    | Base Class | Derived Class | World
—————————————+————————————+———————————————+———————
public       |      y     |       y       |   y
—————————————+————————————+———————————————+———————
protected    |      y     |       y       |   n
—————————————+————————————+———————————————+———————
private      |            |               |    
  or         |      y     |       n       |   n
no accessor  |            |               |

y: accessible
n: not accessible
に基づいて、このJavaのための例をを...私は千個の言葉の価値がほとんどないテーブルだと思います>

まとめ:

  • プライベート:クラス内以外は誰にも見られない
  • 保護中:プライベート + 派生クラスはそれを見ることができます
  • 公共:世界はそれを見ることができます

継承するとき、(一部の言語では) データ メンバーの保護タイプを特定の方向に変更できます。保護されたものから公共のものへ。

プライベート

基底クラスのプライベートメンバーは、その基底クラスのメンバによってアクセスすることができる。

公開:

基底クラスのパブリックメンバは、その基底クラスのメンバー、その派生クラスのメンバーと同様に、基本クラスの外側にある部材と、派生クラスによってアクセスすることができる。

保護:

基底クラスの保護されたメンバーは、基本クラスのメンバーならびにその派生クラスのメンバによってアクセスすることができる。

<時間>

要するに:

プライベートのベース

保護する:誘導基+

の公共:ベース+由来+他のメンバー

私は簡単な答えを見つけたので、あまりにも私の将来の参考のためにそれを掲示すると考えます。

そのリンクからのhttp://www.learncpp .COM / CPP-チュートリアル/ 115-継承・アンド・アクセス指定子/

class Base
{
public:
    int m_nPublic; // can be accessed by anybody
private:
    int m_nPrivate; // can only be accessed by Base member functions (but not derived classes)
protected:
    int m_nProtected; // can be accessed by Base member functions, or derived classes.
};

class Derived: public Base
{
public:
    Derived()
    {
        // Derived's access to Base members is not influenced by the type of inheritance used,
        // so the following is always true:

        m_nPublic = 1; // allowed: can access public base members from derived class
        m_nPrivate = 2; // not allowed: can not access private base members from derived class
        m_nProtected = 3; // allowed: can access protected base members from derived class
    }
};

int main()
{
    Base cBase;
    cBase.m_nPublic = 1; // allowed: can access public members from outside class
    cBase.m_nPrivate = 2; // not allowed: can not access private members from outside class
    cBase.m_nProtected = 3; // not allowed: can not access protected members from outside class
}

これは、本質的に、派生クラスで基本クラスのpublicおよびprotectedメンバーのアクセス保護です。公共の継承を使用すると、派生クラスは、ベースのパブリックおよび保護されたメンバーを見ることができます。 private継承と、それはできません。保護されたと、その由来派生クラスと、任意のクラスがそれらを見ることができます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top