0

C++ は、オブジェクト指向を使用する言語として私が初めて広く使用した言語であり、そのため、私はまだその考えに少し慣れていません。Go (真の OOP システムではなくインターフェイスを使用) から C++ に取り組んでいたゲーム ライブラリを移植しようとしています。

ポイント、バウンディング、ライン、ポリゴンの 4 つのタイプを使用する衝突システムがあります。私がやりたいのは、これらすべてを「コライダー」クラスに抽象化できるようにし、2 つのコライダー オブジェクトを取り、衝突をテストできる関数を持たせることです。次のようになります。

bool Collides(Collider obj1, Collider obj2);

当初は、別のタイプの衝突をテストする各衝突タイプのメソッド (つまり、メソッド OnPoint、OnBounding、OnLine、および OnPolygon) を用意し、「Collider」をこれらすべてのメソッドを必要とする仮想クラスにすることができると考えていましたが、それから、コンパイルのためにクラスが互いに依存するようになるため、C++では不可能であることに気付きました(そうですか?)。

他に何ができるのか少し途方に暮れています。私のデザインのアイデアは夢物語ですか?

4

1 に答える 1

1

必要なのは、最初の引数だけでなく、2 番目の引数でもディスパッチする関数、つまり二重ディスパッチです。これは C++ では直接サポートされていませんが、エミュレートできます。

class Point;
class Line;

class Collider {
public:
  virtual bool Collides(Collider const& x) const = 0;

protected:
  virtual bool Collides(Point const& p) const = 0;
  virtual bool Collides(Line const& l) const = 0;

  friend class Point;
  friend class Line;
};

class Point: public Collider {
public:
  virtual bool Collides(Collider const& x) const {
    // here, the type of this is now Point
    // now, find out what x is and call the overload on this type
    return x.Collides(*this);
  }

protected:
  virtual bool Collides(Point const& p) const {
    return false;
    // we now know that we are a point and checking vs. another point
  }

  virtual bool Collides(Line const& l) const {
    return false;
    // we now know that we are a point and checking vs. a line
  }
};

class Line: public Collider {
public:
  virtual bool Collides(Collider const& x) const {
    // here, the type of this is now Line 
    return x.Collides(*this);
  }

protected:
  virtual bool Collides(Point const& p) const {
    return false;
    // we now know that we are a line and checking vs. a point
  }

  virtual bool Collides(Line const& l) const {
    return false;
    // we now know that we are a line and checking vs. another line
  }
};

現在、2 つのオブジェクトをチェックすると、2 つのランタイム ディスパッチが行われます。

Collider* p = new Point();
Collider* l = new Line();

p->Collides(*l);
// first dynamically dispatches on p to call Point::Collides
// in Collides, this (which is p) now has the static Point. 
// now do the second dispatch on l and use *this as the parametet
// to find the overload.

これは、たとえばVisitor デザイン パターンで使用されます。オブジェクトのセットが固定されているが、それらに対して実行される操作が変更または拡張されることが予想される場合は、Visitor が適切な選択です。

于 2014-04-06T21:53:24.347 に答える