0

この記事の著者は次のように述べています。

「通常、あまりにも多くの他のクラスの内部にアクセスしたくはありません。プライベート継承は、この余分な力 (および責任) の一部を提供します。しかし、プライベート継承は悪ではありません。維持するのにコストがかかるだけです。誰かが何かを変更してあなたのコードを壊す可能性が高くなります。」

privatelyCarから継承する次のコードを想定します。Engine

#include <iostream>
using namespace std;

class Engine
{
    int numCylinders;
    public:
    class exception{};
    Engine(int i) { if( i < 4 ) throw exception(); numCylinders = i; }
    void start() { cout << "Engine started " << numCylinders << " cylinders" << endl; }
};

class Car : private Engine          
{    
    public:
    Car(int i) : Engine(i) {}
    using Engine::start;
};

int main()
{
    try
    {
        Car c(4);
        c.start();
    }
    catch( Engine::exception& )
    {
        cout << "A Car cannot have less than 4 cylinders" << endl;
    }
}

私の質問は次のとおりです。Carたとえば、Engine4 シリンダー未満で、プライベート継承を使用し、基本クラスで保護されたメンバーを使用せずに、このコードをどのように壊すことができますか?

4

4 に答える 4

2

問題は、Car が Engine のコードを壊す可能性があることではなく、Engine を変更することで誰かが Car のコードを壊す可能性があることだと思います。継承は合成よりもはるかに緊密な結合を表すため、Engine の変更は、エンジンを含むクラスではなく継承するクラスを壊す可能性が高くなります。C++ の場合、Car にエンジン ポインターまたはスマート ポインターを含めることにより、さらに疎結合が実現されます。

于 2012-02-08T18:28:36.107 に答える
2

継承がメンバーシップよりもはるかに緊密な結合を導入する 1 つの方法は、派生クラスと基本クラスの名前空間が混在していることです。したがって、派生クラスのコンテキストでの名前の意味は、基本クラスが導入する名前に依存し、通常のオーバーライド/非表示効果があります。基本クラスの変更は、必ずしも明確に特定できるとは限らない、または有用な診断をすぐに生成する派生クラスのコードに影響を与える可能性があります。対照的に、メンバー オブジェクトのインターフェイスが変更された場合、破損する可能性があるのは、実際にメンバー オブジェクトに言及しているコードです。

于 2012-02-08T18:26:55.020 に答える
1

Car が Engine::numCylinders を設定できるとは思えません (少なくとも生メモリへのアクセスなどの汚いトリックがなければ)。この記事の例では保護されたメソッドを使用しており、プライベート メンバーを使用しています。

ところで: この記事は「可能な場合はコンポジションを使用する」で始まります。車はエンジンがありますが、エンジンではありません。AがBから派生した場合、これは通常ABであることを表します。

于 2012-02-08T18:31:15.997 に答える
0

この記事の著者は、前のポイントで、プライベート継承を使用することの「欠点」のいくつかについて言及しています

  • 車ごとに複数のエンジンを含める場合は、単純な構成のバリアントが必要です
  • private-inheritance バリアントは、不要な多重継承を導入する可能性があります
  • プライベート継承バリアントにより、Car のメンバーは Car* を Engine* に変換できます。
  • private-inheritance バリアントは、基本クラスの保護されたメンバーへのアクセスを許可します
  • private-inheritance バリアントにより、Car は Engine の仮想関数をオーバーライドできます
  • private-inheritance バリアントを使用すると、エンジンの start() メソッドを呼び出すだけの start() メソッドを Car に与えることが少し簡単になります (28 文字に対して 20 文字)。
于 2012-02-08T18:31:12.613 に答える