c++ - 英語 - 継承されたメンバーは使用できません




プライベート、パブリック、および保護された継承の違い (10)

プライベート:

基本クラスのプライベートメンバーにアクセスできるのは、その基本クラスのメンバーだけです。

パブリック:

基本クラスのパブリックメンバーには、その基本クラスのメンバー、その派生クラスのメンバー、および基本クラスおよび派生クラスの外部にあるメンバーからアクセスできます。

保護された:

基本クラスの保護されたメンバーには、基本クラスのメンバーだけでなく、その派生クラスのメンバーもアクセスできます。

要するに:

プライベート :ベース

保護された :base + derived

public :base + derived +他のメンバー

C ++のpublicprivate 、およびprotected継承の違いは何ですか? 私がSOで見つけたすべての質問は、特定のケースを扱っています。


1)パブリック継承

a。 Baseクラスのプライベートメンバーは、Derivedクラスではアクセスできません。

b。 Baseクラスの保護されたメンバーは、Derivedクラスで保護されたままです。

c。 Baseクラスのパブリックメンバーは、Derivedクラスで公開されたままです。

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

2)保護された継承

a。 Baseクラスのプライベートメンバーは、Derivedクラスではアクセスできません。

b。 Baseクラスの保護されたメンバーは、Derivedクラスで保護されたままです。

c。 BaseクラスのパブリックメンバーもDerivedクラスの保護メンバーになります。

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

3)プライベート継承

a。 Baseクラスのプライベートメンバーは、Derivedクラスではアクセスできません。

b。 BaseクラスのprotectedおよびpublicメンバーはDerivedクラスのプライベートメンバーになります。

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


これらの3つのキーワードは、 可視性継承モデルを指定するために全く異なるコンテキストでも使用されます。

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

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

コンポーネントがpublicとして宣言され、そのクラスがpublicとして継承される場合、その結果のアクセスpublicになります

例:

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

 class Sub : private Super {};

 class Subsub : public Sub {};

Subsubクラスの変数pqrに対するアクセスはnoneです。

もう一つの例:

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

z変数yzの結果としてのアクセスは保護され 、変数xnoneになります。

より詳細な例:

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クラスは、新しい変数も新しい関数も導入しません。 これは、 Superクラスが実際にSuperクラスのオブジェクトのコピーであることの後で、 Subクラスのオブジェクトがすべての特性を継承することを意味しますか?

いいえ 。 それはしません。

次のコードをコンパイルすると、 putメソッドとgetメソッドにアクセスできないというコンパイルエラーだけが表示されます。 どうして?

visibility指定子を省略すると、コンパイラは、いわゆるプライベート継承を適用することを前提としています。 これは、すべてのパブリックスーパークラスコンポーネントがプライベートアクセスになることを意味し、プライベートスーパークラスコンポーネントには全くアクセスできません。 したがって、サブクラス内で後者を使用することはできません。

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

class Sub : public Super { };

誤解されることはありません。つまり、Super変数のプライベートコンポーネント(ストレージ変数など)がやや魔法のように公開されることを意味するわけではありません。 私的な構成要素は非公開のままであり、 一般の人公開されます。

Subクラスのオブジェクトは、 Superクラスから作成された古い型の兄弟と "ほぼ同じ"ことができます。 サブクラスであるという事実は、クラスがスーパークラスのプライベートコンポーネントへのアクセスを失ったことも意味します 。 我々は、ストレージ変数を直接操作することができるSubクラスのメンバ関数を書くことはできません。

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

はい

第3のアクセスレベルは保護されたものです。 プロテクトされたキーワードは、それマークされたコンポーネントが、サブクラスのいずれかで使用され、世界の他の国々にプライベートなもののように見える場合に、公共のよう振る舞うことを意味します 。 - これは公開されている継承されたクラス(この例のSuperクラスなど)の場合にのみ当てはまります。

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クラスの新しい機能は重要なことです: Superクラスからストレージ変数にアクセスします

変数がプライベートとして宣言されていれば、それは不可能です。 メイン関数のスコープでは、変数は隠れたままになりますので、次のような記述があれば:

object.storage = 0;

コンパイラはerror: 'int Super::storage' is protectedあることを通知しますerror: 'int Super::storage' is protectedます。

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

storage = 101

その質問に答えるために、メンバーのアクセサをまず自分の言葉で表現したいと思います。 すでにこれを知っている場合は、「次へ」という見出しにスキップしてください。

私が知っているアクセサーには、 publicprotectedprivate 3つがあります。

Let:

class Base {
    public:
        int publicMember;
    protected:
        int protectedMember;
    private:
        int privateMember;
};
  • Base認識しているすべての人は、 BasepublicMemberが含まれていることも認識していpublicMember
  • BaseprotectedMemberが含まprotectedMemberていることは、子(およびその子)のみが認識してprotectedMemberます。
  • Base privateMember認識していません。

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

次:

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

  • 継承がpublic場合、 BaseおよびChild認識しているすべての人は、 ChildBaseから継承することも認識しています。
  • 継承がprotected場合、 Childとその子のみがBaseから継承していることを認識しています。
  • 継承がprivateである場合、 Child以外の誰も継承を認識していません。

パブリック継承は、IS-A関係をモデル化します。 と

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

すべてのD Bです。

プライベート継承は、IS-IMPLEMENTED-USING関係(またはそれが呼び出されたもの)をモデル化します。 と

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

DBではありませんが、すべてのDはその実装でBを使用します。 プライベート継承は、代わりに包含を使用することによって常に排除することができます:

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

このDBを使用して実装できます。この場合はb_を使用します。 包含は継承よりも型間の密接な結びつきが少ないので、一般的にはそれが好ましいはずです。 プライベート継承の代わりに包含を使用することは、プライベート継承ほど便利ではない場合があります。 しばしばそれは怠け者であることのための不用意な言い訳です。

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


保護されたデータメンバーには、クラスを継承するすべてのクラスからアクセスできます。 しかし、私的なデータメンバーはできません。 私たちには次のものがあるとしましょう:

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

あなたのエクステンションの中からthis.myPrivateMemberを参照することはできません。 ただし、 this.myProtectedMemberthis.myProtectedMemberます。 値はまだカプセル化されているので、このクラスのインスタンス化がmyObj場合、 myObj.myProtectedMemberは機能しません。したがって、関数内ではprivateデータメンバーと似ています。


概要:

  • プライベート:クラス内を除いて誰も見ることができません
  • 保護された:プライベート+派生クラスはそれを見ることができます
  • 公開:世界はそれを見ることができます

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


私は簡単な答えを見つけたので、将来の参考のためにそれを投稿することも考えました。

そのリンクからhttp://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/

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
}

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

this Javaの例に基づいて...私は1000の言葉の価値がある小さなテーブルを考える:)


Member in base class : Private   Protected   Public   

継承型オブジェクト継承

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




c++-faq