さて、この主題についての十分な情報があります。たとえば、このスレッドは私には非常に明確でした:プライベート、パブリック、および保護された継承の違い
1点を除いて; なぜそれが役立つのですか?
さて、この主題についての十分な情報があります。たとえば、このスレッドは私には非常に明確でした:プライベート、パブリック、および保護された継承の違い
1点を除いて; なぜそれが役立つのですか?
公開継承を使用してis-a 関係を反映します。これは、特に仮想関数と組み合わせた継承の主な用途です。新しいコードによる古いコードの再利用だけでなく、古いコードによる新しいコードの再利用も可能です。(実行時の仮想関数ディスパッチのため)。
例外的な状況では、プライベート継承を使用してis-implemented-in-term-of 関係を反映します。これはよく使われるパターンであり、多くの場合、同等の目標は構成によって達成できます (基本クラスをデータ メンバーとして持つ)。もう 1 つの欠点は、同じ基本クラスの複数の継承 (2 回以上の削除) を簡単に行うことができ、いわゆるDiamond Problemにつながることです。
protected inheritanceの使用は避けてください。クラス インターフェイスがクライアント依存であることを示唆しています (派生クラスと世界)。多くの場合、これは複数の責任を持つクラスが原因であり、個別のクラスへのリファクタリングが適切であることを示唆しています。
この質問に対する答えは、言語機能ではなく、クラス インターフェイスとデータのカプセル化に関するものです。
問題をより適切に解決する他のオプション (継承ではなく構成を使用するなど) が利用できることが多いため、保護されたプライベート継承の使用例はかなり限られています。ただし、何らかのタイプから継承する必要がある場合(たとえば、サードパーティ ライブラリとのインターフェイス) がありますが、(クラスのユーザー インターフェイスに関連する理由で) ベースから継承されたほとんどのメンバーを非表示にすることを強くお勧めします。新しいタイプのユーザーからのクラス。典型的なシナリオは、型が内部使用のために特定のクラスのメンバー関数を持つ必要がある場合ですが、クラス自体の外部から呼び出された場合、新しい型のロジックが壊れます。
これらの状況では、private
またはprotected
継承を使用する必要があります (インターフェイスをさらに派生したクラスに同様に制限する必要があるかどうかによって異なります。
ただし、これはすべて、クラスのユーザーにクラスの使用方法を (強く) 示唆しているだけであることに注意してください。基本クラスで公開されていた特定の機能を非表示にするために、公開インターフェイスを調整しています。これは厳密に言えば、これらのメンバーへのアクセスを妨げるものではありません。派生クラスへのポインターをベースへのポインターにキャストし、その方法で「非表示の」リソースにアクセスできるためです。
データのカプセル化がすべてです。
http://en.wikipedia.org/wiki/Encapsulation_(object-oriented_programming)
クラスの「内部」データを他のクラスから保護することをお勧めします。利点は次のとおりです。
protected
代わりにを使用するオプションがあるprivate
と、コードをサブクラス化して拡張するのも簡単になります。
プライベート:クラスのプライベート メンバーには、クラス関数、コンストラクター、およびデストラクターからのみアクセスできます。クラスを使用するクライアントは、それらにアクセスできなくなります。たとえば、リストクラスを実装していて、リストのサイズを追跡したい場合は、プライベート変数 (listSizeP
たとえば) が必要です。これを行うのは、クライアントが要素を挿入せずにリストのサイズを変更できないようにするためです。
パブリック:パブリック メンバーは、クライアントからもアクセスできます。上記のリストの例では、関数はinsert
およびのerase
ように公開する必要があります。
Protected:クラスの保護されたメンバーは、プライベート メンバーと同様に、クラス関数からのみアクセスできますが、このクラスによって継承されたクラスからもアクセスできます (実際には、派生クラスがベースを継承する方法によって異なります。そうでない場合パブリック継承の場合、派生クラスは基底クラスのプライベート メンバーにアクセスできません。そのため、継承の最も一般的な方法はパブリック継承です)。例:
#include <iostream>
using namespace std;
class Base {
public:
int num;
public:
Base(int x=0) : num(x) {}
};
class Derived : public Base {
public:
Derived(int x=0) : Base(x) {}
void tell() { cout << "num: " << num << endl; }
};
int main() {
Derived D(4);
D.tell(); // would cause error if num was private
return 0;
}