C++ で保護された継承が「必要」な例はありますか?
-
09-06-2019 - |
質問
まれなケースを見てきましたが、 プライベート 継承が必要でしたが、次のようなケースに遭遇したことはありません 保護された 継承が必要です。誰かが例を持っていますか?
解決
ここの人々は、Protected クラスの継承と Protected メソッドを誤解しているようです。
FWIW、私は保護されたクラスの継承を使用している人を見たことがありません。私の記憶が正しければ、Stroustrup は「保護された」レベルが C++ の間違いであるとさえ考えていたと思います。その保護レベルを削除し、パブリックとプライベートのみに依存すれば、できないことはほとんどありません。
他のヒント
保護された継承の使用例は非常にまれです。活用したいところです 共分散:
struct base {
virtual ~base() {}
virtual base & getBase() = 0;
};
struct d1 : private /* protected */ base {
virtual base & getBase() {
return this;
}
};
struct d2 : private /* protected */ d1 {
virtual d1 & getBase () {
return this;
}
};
前のスニペットは、「getBase」関数を提供することで、何らかの理由でその基本クラスを非表示にし、基本クラスとその関数の制御された可視性を提供しようとしました。
ただし、構造体では失敗します d2
, 、 以来 d2
それは知りません d1
から派生した base
. 。したがって、 covariance
動作しないでしょう。これを回避する方法は、継承が d2 で見えるように、保護されたものを派生することです。
これを使用する同様の例は、次のように派生する場合です。 std::ostream
, 、しかし、ランダムな人があなたのストリームに書き込むことは望ましくありません。仮想を提供できます getStream
を返す関数 std::ostream&
. 。この関数は、次の操作に備えてストリームの準備を行うことができます。たとえば、特定のマニピュレータを入れるなどです。
std::ostream& d2::getStream() {
this->width(10);
return *this;
}
logger.getStream() << "we are padded";
C++ FAQ Lite プライベート継承の使用が正当な解決策であるケースについての言及 (「 [24.3.] どれを優先すべきですか:合成かプライベート継承か?)。それは、仮想関数を介してプライベート基本クラス内から派生クラスを呼び出したい場合です (この場合、 derivedFunction()
):
class SomeImplementationClass
{
protected:
void service() {
derivedFunction();
}
virtual void derivedFunction() = 0;
// virtual destructor etc
};
class Derived : private SomeImplementationClass
{
void someFunction() {
service();
}
virtual void derivedFunction() {
// ...
}
// ...
};
ここで、クラス Derived から派生させ、使用したい場合は、 Base::service()
派生クラス内から(移動したいとします) Derived::someFunction()
派生クラスに)、これを達成する最も簡単な方法は、のプライベート継承を変更することです。 Base
保護された継承に。
申し訳ありませんが、これ以上具体的な例が思いつきません。個人的には、「継承関係を保護するか非公開にするか」という議論で時間を無駄にすることを避けるために、すべての継承を公開することを好みます。