プライベートおよび保護されたメンバー:C ++


276

privateprotectedクラスのメンバーの違いについて誰かに教えてもらえますか?

私はクラスの外と呼ばれていない変数や関数がなされるべきであることを、ベストプラクティスの規則から理解privateが、私を見て- MFCのプロジェクト、MFCが賛成に思えますprotected

違いは何ですか?どちらを使用すればよいですか?

回答:


374

プライベートメンバーは、それらを定義するクラス内でのみアクセスできます。

保護されたメンバーは、それらを定義するクラスおよびそのクラスから継承するクラスでアクセスできます。

編集:どちらも、クラスの友達がアクセスできます。保護されたメンバーの場合は、派生クラスの友達もアクセスできます。

編集2:問題のコンテキストで意味のあるものを使用します。結合を減らして基本クラスの実装を保護するために、できる限りメンバーをプライベートにしようとする必要がありますが、それが不可能な場合は、保護されたメンバーを使用してください。この問題についての理解を深めるには、C ++ FAQを確認してください。保護された変数に関するこの質問も役立つかもしれません。


12
C ++ FAQ Liteへのリンクはisocpp.org/wiki/faq/basics-of-inheritance
avner

134

クラスAのパブリックメンバーは、誰でもアクセスできます。

クラスAの保護されたメンバーは、Aのコードの外部からはアクセスできませんが、Aから派生したクラスのコードからはアクセスできます。

クラスAのプライベートメンバーは、Aのコードの外部、またはAから派生したクラスのコードからはアクセスできません。

したがって、最終的には、保護されたものかプライベートなものかを選択することで、次の質問に答えることができます。

デフォルトでは、派生クラスを信頼しないと想定し、メンバーを非公開にします。派生クラスへの母クラスの内部への無料アクセスを与える非常に正当な理由がある場合、それらを保護することができます。


派生クラスはクラスのタイプである必要があり、基本クラスの保護されたデータは派生クラスのデータの一部です。派生クラスの作成者は、このデータを適切に処理することが期待されているか、バグです。ただし、基本クラスのプライベートデータは、派生クラスの作成者が制御するものではありません。
CashCow 2016年

@CashCow the protected data of the base class is part of the data of the derived class.確かに。では、派生クラスの作成者が自分のクラスではなく自分のクラスでそのデータを宣言するようにした方がいいのではないでしょうか。...:-) ... The writer of the derived class is expected to handle this data properly or it is a bug.NVIパターンの目的は、メソッド、派生クラスのライターが階層に与えるダメージを制限します。保護されたメソッドはすでに潜在的な問題です。保護された状態を使用してこれを悪化させることが正しいアプローチであると私は確信していません。
paercebal

アクセスするためには、基本クラスに仮想「ゲッター」が必要です。また、中間のクラスを使用してデータパターンを実装するさまざまな方法を実行できますが、そうすることが必ずしも現実的ではありません。たとえば、C ++ではほとんどの場合「const」修飾子を必要としない言語で一般的な「パターン」は、読み取り専用の基本クラスと書き込み可能な派生クラスを持つことです。C ++では、データをロード(初期化)するために複数の可能な方法が必要なため、これも便利です。
CashCow 2016年

それにはさまざまな方法があります。シリアライゼーションクラスを友だちにしましょう。すべてのデータをパブリックアクセスを持つ構造体に入れますが、クラスにはこの変数のプライベートメンバーがあります...保護されたメンバーと派生クラスを使用して、ソースから簡単に読み込むことができます。
CashCow 2016年

63

保護されたメンバーには、派生クラスからアクセスできます。プライベートのものはできません。

class Base {

private: 
  int MyPrivateInt;
protected: 
  int MyProtectedInt;
public:
  int MyPublicInt;
};

class Derived : Base
{
public:
  int foo1()  { return MyPrivateInt;} // Won't compile!
  int foo2()  { return MyProtectedInt;} // OK  
  int foo3()  { return MyPublicInt;} // OK
};‌‌

class Unrelated 
{
private:
  Base B;
public:
  int foo1()  { return B.MyPrivateInt;} // Won't compile!
  int foo2()  { return B.MyProtectedInt;} // Won't compile
  int foo3()  { return B.MyPublicInt;} // OK
};

「ベストプラクティス」に関しては、状況によって異なります。誰かが既存のクラスから新しいクラスを派生させ、内部メンバーへのアクセスを必要とする可能性があるかすかな可能性さえある場合は、プライベートではなく保護します。それらがプライベートの場合、クラスを簡単に継承するのが難しくなる可能性があります。


3
私は違うことを頼みます:サブクラスがそれを必要としないだろうというかすかな可能性があるならば、それをプライベートにしてください。クラスをサブクラス化するつもりがない限り、テンプレートメソッドパターンを使用します。
xtofl 2008年

23

MFCが保護を支持する理由は、それがフレームワークであるためです。おそらく、MFCクラスをサブクラス化する必要があります。その場合、クラスの一般的な使用からは見えないメソッドにアクセスするには、保護されたインターフェイスが必要です。


9

それはすべて、何をしたいか、そして派生クラスが何を見たいかによって異なります。

class A
{
private:
    int _privInt = 0;
    int privFunc(){return 0;}
    virtual int privVirtFunc(){return 0;}
protected:
    int _protInt = 0;
    int protFunc(){return 0;}
public:
    int _publInt = 0;
    int publFunc()
    {
         return privVirtFunc();
    }
};

class B : public A
{
private:
    virtual int privVirtFunc(){return 1;}
public:
    void func()
    {
        _privInt = 1; // wont work
        _protInt = 1; // will work
        _publInt = 1; // will work
        privFunc(); // wont work
        privVirtFunc(); // wont work
        protFunc(); // will work
        publFunc(); // will return 1 since it's overridden in this class
    }
}

6

マークされた属性とメソッド(protectedプライベートのものとは異なり)は、依然としてサブクラスで表示されます。

可能なサブクラスでメソッドをオーバーライドする可能性を使用または提供したくない場合を除き、私はそれらを作成しますprivate


2
派生クラスは、ベースのプライベート仮想関数をオーバーライドできます
James Hopkin

6

もちろん、保護されたメンバー変数の質問を見てください。class結合を減らすために、(C ++ sesと同じように)プライベートをデフォルトとして使用することをお勧めします。保護されたメンバー変数は、常に悪い考えです。保護されたメンバー関数は、たとえばテンプレートメソッドパターンに使用できます。


おかしい、私はあなたの記事を見る前にそれを私の投稿に編集しました。羽の鳥が同じリンクにつまずくので賛成:)
Firas Assaad 08/10/22

4

保護されたメンバーには、クラスの子孫、および同じモジュール内のコードによってのみアクセスできます。プライベートメンバーには、それらが宣言されているクラスと、同じモジュール内のコードによってのみアクセスできます。

もちろん、フレンド関数はこれをウィンドウの外に出しますが、まあ。


4

プライベートメンバーにはクラス内からのみアクセスでき、保護されたメンバーにはクラスおよび派生クラスからアクセスできます。これはオブジェクト指向言語の継承機能です。

C ++でプライベート、保護、パブリックの継承を設定できます。これにより、継承階層でアクセスできる派生クラスが決まります。たとえば、C#にはパブリック継承のみがあります。


3

プライベート =母船(基本クラス)のみがアクセス可能(つまり、私の両親のみが私の両親の寝室に入ることができます)

protected =母艦(基本クラス)と彼女の娘(つまり、私の親だけが私の親の寝室に入ることができますが、息子/娘に親の寝室に入る許可を与えました)によってアクセス可能

public =母艦(基本クラス)、娘、その他すべての人がアクセスできます(つまり、私の親の寝室に入ることができるのは私の親だけですが、それはハウスパーティーです-mi casa su casa)


2

派生クラスの保護されたメンバーをフェッチおよび更新するためにパブリックメンバー関数は必要ないため、これによりコードの効率が向上し、記述する必要があるコードの量が減少します。ただし、派生クラスのプログラマは、自分が何をしているのかを知っているはずです。


クラス宣言に実装されたインライン関数はいつでも使用できます。コンパイラーはそれを最適化します(たとえば、プライベートメンバー変数への読み取り専用アクセスを強制する良い方法です)。
ポールサンダース

2

privateメンバーデータには推奨されます。C ++クラスのメンバーはprivateデフォルトでです。

public意見の問題ですが、メンバー関数には推奨されます。少なくともいくつかのメソッドはアクセス可能でなければなりません。publicすべての人がアクセスできます。これは最も柔軟なオプションであり、安全性は最も低くなります。だれでもそれらを使用でき、だれでもそれらを誤用することができます。

privateまったくアクセスできません。誰もクラスの外では使用できませんし、誤用することもできません。派生クラスにもありません。

protected派生クラスで使用できるため、妥協です。クラスから派生するときは、基本クラスをよく理解していて、これらのメンバーを誤用しないように注意します。

MFCは、Windows APIのためのC ++ラッパーです、それは好むpublicprotected。Visual Studioで生成されたクラスは、醜いの混在持っウィザードprotectedpublicおよびprivateメンバーを。しかし、MFCクラス自体にはいくつかのロジックがあります。

などのメンバーSetWindowTextpublic、これらのメンバーにアクセスする必要があることが多いためです。

などのメンバーOnLButtonDownは、ウィンドウが受け取った通知を処理します。これらはアクセスされるべきではないため、アクセスされますprotected。これらの関数をオーバーライドするために、派生クラスでそれらに引き続きアクセスできます。

一部のメンバーはスレッドとメッセージループを実行する必要があります。これらのメンバーにはアクセスまたはオーバーライドしないでください。そのため、次のように宣言されています。 private

C ++構造では、メンバーはpublicデフォルトです。構造体は通常、メソッドではなくデータのみに使用されるため、public宣言は安全と見なされます。


1
「C ++クラスのメンバーはデフォルトで保護されています」と書きます。標準によれば、定義で使用されたキーワードに応じて、デフォルトでプライベートまたはパブリックになります(14p3)。ここでマイクロソフトは標準から逸脱していますか?
Alexander Klauer

@AlexanderKlauer私は間違っていました、それprivateはVisual Studioのデフォルトです。それはだprivate、それは決していないだけでなく、GCCではデフォルトでpublic、デフォルトで。私が再び間違っていない限り。参照している規格が見つかりません。
Barmak Shemirani

申し訳ありませんが、もっと具体的に説明する必要がありました。私はC ++ 17標準を参照していました。C ++ 11標準は、11p3でも同じ表現です。回答を更新していただけませんか?ありがとう!
アレクサンダークラエル

1

プライベートメンバーは、それが宣言されている同じクラスでのみアクセスできます。保護されたメンバーは、継承されているクラスと共に宣言されているクラスでアクセスできます。


1
  • プライベート:アクセス指定子です。デフォルトでは、インスタンス(メンバー)変数またはc ++ / javaのクラスのメソッドはプライベートです。継承中、コードとデータは常に継承されますが、クラスの外部からはアクセスできません。データメンバーをプライベートとして宣言して、メンバー変数を直接変更できないようにし、プライベートメンバーを変更するためのパブリックゲッターとセッターを提供することができます。そして、この概念は常にビジネスルールに適用されます。

  • 保護:アクセス指定子でもあります。C ++では、保護されたメンバーはクラス内および継承されたクラスにアクセスできますが、クラスの外部にはアクセスできません。Javaでは、保護されたメンバーは、クラス内、継承されたクラス、および同じパッケージ内のすべてのクラスにアクセスできます。


0

保護された非静的基本クラスメンバーには、次のいずれかを使用して、その基本クラスから派生したクラスのメンバーおよびフレンドがアクセスできます。

  • 直接または間接的に派生したクラスへのポインター
  • 直接的または間接的に派生したクラスへの参照
  • 直接的または間接的に派生したクラスのオブジェクト

0

Private:クラスメンバー関数とフレンド関数またはフレンドクラスからアクセスできます。C ++クラスの場合、これはデフォルトのアクセス指定子です。

保護:クラスメンバー関数、フレンド関数、フレンドクラスと派生クラスからアクセスできます。

  • クラスメンバー変数または関数(typedefや内部クラスを含む)を、必要に応じてプライベートまたは保護された状態に保つことができます。
  • ほとんどの場合、クラスメンバーをプライベートとして保持し、カプセル化するget / set関数を追加します。これはコードのメンテナンスに役立ちます。
  • 一般にプライベート関数は、パブリック関数をモジュール化したままにする場合や、コード全体を単一の関数に書き込むのではなく、繰り返しコードを排除する場合に使用されます。これはコードのメンテナンスに役立ちます。

詳細については、このリンク参照してください


-2

プライベートおよび保護されたアクセス修飾子は、基本クラスの保護されたメンバーが子(派生)クラスの基本クラスのスコープ外でアクセスできることと同じです。継承についても同様です。ただし、プライベート修飾子を使用すると、基本クラスのメンバーには、基本クラスのスコープまたはコードとそのフレンド関数でのみアクセスできます '' ''


5
あなたの答えは他の答えにどのような価値をもたらしますか?
HermannDöppes16年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.