1

私がこの基本クラスを持っていると仮定します:

struct Vehicle {
  //"op" stands for the operator of the vehicle
  //examples: pilot, truck driver, etc.
  virtual void insert_op(Op op) = 0;
  //other members...
};

そして、これらの2つのサブクラス

struct Truck : public Vehicle {
  void insert_op(Op op) override {
    //prepare Truck with truck driver
  }
};

struct Airplaine : public Vehicle {
  void insert_op(Op op) override {
    //prepare Airplaine with pilot
  }
};

ご想像のとおり、これはもう1つの階層です。

struct Op {};
struct TruckDriver : public Op {};
struct Pilot : public Op {};

あなたはすでに問題を見ていますね?トラックドライバーのみを受け入れるようにトラックを強制し、パイロットのみを受け入れるようにエアプレーンを強制したいのですが、これは現在の設計では不可能です。C ++では、オーバーライドされた仮想のdiffパラメーターは許可されていません。

insert_opの各サブクラス実装で「Op」タイプの実行時型チェックを実行できると思いますが、それは本当に醜い解決策のように聞こえますが、コンパイル時に強制されません。

何か方法はありますか?

4

5 に答える 5

3

あなたのVehicle言うvirtual void insert_op(Op op)ことは、「すべての車両が任意の車両を受け入れることができる」という意味Opです。

したがって、あなたの設計によると、 aはサブクラスTruckの有効な候補ではありません。これは、何も受け入れることができないためです。 sのみを受け入れることができます。Vehicle OpTruckDriver

関連:リスコフ置換原理


問題は実装ではなく設計にあります。クラス階層を単純化することをお勧めします。本当に多くのクラスと継承が必要ですか? タイプを識別するフィールドを持つVehicleandをそのまま使用できますか?Op


設計上の問題をさらに説明しましょう。

Amethod を持つオブジェクトを想定しますmanVehicle(Vehicle&)Truckは Vehicle のサブクラスであるため、このメソッドを type のオブジェクトで呼び出すことができますTruck

ただし、 の実装にAは、具体的な s の型についての手がかりがありませんVehicle。すべての車両にメソッドがあることだけを知っているため、車両が実際には であっても、のinsert_op(Op)ように呼び出しを試みることは有効です。insert_op(Pilot())Truck

結論:

  • コンパイル時のチェックすら不可能

  • ランタイムチェックは機能する可能性があります...

    • しかし、敷物の下で問題を一掃するだけです. sのユーザーは、任意Vehicleの を呼び出せることを期待しています。insert_op(Op)Vehicle

Vehicle解決策は、インターフェイスを次のように変更することです。

struct Vehicle {
  virtual bool can_insert_op(Op op) = 0;
  virtual void insert_op(Op op) = 0;
};

指定されたを満たす s でinsert_opのみ呼び出すことができることを呼び出し元が認識できるように、それを文書化します。または類似のもの ( 「この車両には無効な操作タイプ」からの文書化された例外など) - このインターフェースの文書化された部分である限り、何でも機能します。Opcan_insert_opVehicleinsert_op


ところで、技術的な注意点:これらのメソッドはOp、不要なコピーやスライスを避けるために、ポインターまたは参照をコピーする代わりに取得する必要があります。

于 2013-02-09T11:06:28.620 に答える
0

どうですか:

struct Vehicle {
  //"op" stands for the operator of the vehicle
  //examples: pilot, truck driver, etc.
  virtual void insert_op(Op op) = 0;
  virtual bool validate_op(Op op);
  //other members...
};

struct Truck : public Vehicle {
  void insert_op(Op op) override {
    if (validate_op(op)) {
        //prepare Truck with truck driver
    }
  }
  bool validate_op(Op op) override {
    //check if this is a valid truck driver
    return ( typeid(op)==typeid(TruckDriver) );
  }
};

の一般的な定義を維持してinsert_op、いくつかの検証を行うことができます。

于 2013-02-09T11:37:57.017 に答える
0

Vehicle サブクラスは、それぞれ適切な Operator を作成する必要があります。演算子を設定するメソッドはありません。Vehicle は get_operator メソッドを持つことができますが、それだけです。

これは実際の階層ではないと思います (ゲームなどを作成している場合を除きます)。実際の階層を表示すると、より良い解決策を提案するのに役立つ場合があります。

于 2013-02-09T11:12:58.287 に答える
0

OOD に対して検索しないでください。トラックの運転手が運転手の子である場合、それは運転手ですが、他の機能があります。あなたの場合、ドライバーは許可されていません。サブトラックのドライバーではありません。現在の設計に固執したい場合は、想定どおりに fn の開始時にチェックを行う必要があります。ポリモーフィズムはコンパイル時にエラーが発生しないように設計されているため、コンパイル時間に依存しない実行時の動的バインディングです。

于 2013-02-09T11:27:18.383 に答える