3

Thinking in C++Vol1(P-33):

構成には非常に柔軟性があります。新しいクラスのメンバーオブジェクトは通常プライベートであるため、クラスを使用しているクライアントプログラマーはそれらにアクセスできません。これにより、既存のクライアントコードを乱すことなく、これらのメンバーを変更できます。
実行時にメンバーオブジェクトを変更して、プログラムの動作を動的に変更することもできます。次に説明する継承には、コンパイラが継承で作成されたクラスにコンパイル時の制限を課す必要があるため、この柔軟性はありません。

コンポジションで実行時にメンバーオブジェクトを変更するにはどうすればよいですか?
クラス宣言が書かれるときにオブジェクトは含まれていませんか?

class car
{
private:
engine obj;
}

したがって、ここでクラスにはクラスcarのオブジェクトが含まれていますengine。実行時にこれをどのように変更できますか?

それとも私はいくつかのポイントを逃していますか?

4

3 に答える 3

7

代わりに、メンバーオブジェクトへのポインタを使用してみてください。

class car {
    engine *obj;
}

rotary_engineこれで、実行時にまたはのインスタンスを使用するかどうv8_engineかを選択できますflux_capacitor_engine

もちろん、aunique_ptrやaのようなものを使用shared_ptrして、メンバーオブジェクトの所有権と存続期間を管理することもできます。

于 2012-12-16T07:21:46.010 に答える
1

それは確かに少し漠然とした声明です。

構成はhas-a関係を定義します。つまり、carを持っていengineます。あなたはあなたの車のエンジンを交換することができます、そして車はまだ車のままです。

継承はis-a関係を定義します。つまり、車をエンジンから継承するものとして定義した場合、それはを意味carengineます。エンジンを変更すると、車自体のタイプが変更されます。基本クラスを変更すると、派生クラスが自動的に変更されます。コンポジションを使用する場合、この制約は存在しません。

したがって、あなたの例では、構成が正しい方法です。

于 2012-12-16T07:27:21.620 に答える
0

純粋な構成の場合、実行時の変更も可能です。

class Car {
private:
   CarPart &get_part(int i) const { 
        switch(i) {
            case 0: return e;
            case 1: return w1;
            case 2: return w2;
            case 3: return w3;
            case 4: return w4;
        }
   }
private:
   Engine e;
   Wheel w1, w2, w3, w4;
};

たとえば、プロパティの設定は簡単です。

void set_property(int id, std::string name, int value) {
    CarPart &p = get_part(id);
    p.set(name, value);
}

これはあなたが得ることができるのとほぼ同じくらい動的です...

于 2012-12-16T09:21:41.277 に答える