3

私は次のクラスを持っています:

Collider (abstract based class)
BoxCollider
MeshCollider
SphereCollider

最後の3つはColliderから継承します。

ユースケースは、各コライダーが他のコライダーのいずれかと衝突するかどうかをチェックできるようにする必要があるということです。

呼び出しはColliderクラスにあり、次のようになります。

void Collider::checkCollisionsWithOtherColliders()
{
for(std::vector<Collider*>::iterator it ....)
{
if(this->isCollidingWith(*it){...}
}
}

isCollidingWithをどのように定義すべきかという問題が発生します

コライダーのペアごとに定義する必要があると思います。つまり、各コライダータイプには、引数として各タイプのコライダーに対してこのメ​​ソッドのバージョンが必要です。たとえば、SphereColliderでは次のようになります。

class SphereCollider : public Collider
{

bool isCollidingWith(SphereCollider* c){..}
bool isCollidingWith(BoxCollider* c){..}
bool isCollidingWith(MeshCollider* c){..}

};

このようなメソッドがCollider基本クラスを介してアクセス可能であることを確認するには、次のように定義する必要があります。

class Collider
{
virtual bool isCollidingWith(SphereCollider* c){..}
virtual bool isCollidingWith(BoxCollider* c){..}
.. and so on
};

また、呼び出しthis->isCollidingWith(*it)は派生クラスではなくColliderへのポインターのみを受け取るため、リストされている仮想メソッドの適切なメソッドが実行時に自動的に取得されることを望みます。ただし、これは当てはまらないようです。パラメーターはColliderだけなので、Collider*パラメーターだけのメソッドを探します。

私が考えることができる唯一の解決策は、Colliderで定義することです。

bool isCollidingWith(Collider* collider)
{
if (0 != dynamic_cast<SphereCollider*>(collider))
return isCollidingWith(dynamic_cast<SphereCollider*>(collider));
else if (0 != dynamic_cast<BoxCollider*>(collider))
return isCollidingWith(dynamic_cast<BoxCollider*>(collider));
else if ...
}

これは本当にエレガントではありません。そのような状況を処理する他の(適切な)方法はありますか?ありがとう!

4

2 に答える 2

4

二重発送の場合です。すでに広く使われているイディオムであるため、ここでは詳しく説明しません。ウィキペディアのページが廃止されたとしても、この用語を使った単純な Google 検索で良い結果が得られるでしょう。

于 2012-11-05T19:08:19.190 に答える
-1

BoxCollider、MeshCollider、および SphereCollider を Collider から継承しているため、各クラスのパラメーターを受け入れるために 3 つの異なるメソッドを作成する必要はありません。これが OOP が素晴らしい理由です。

これを使用できます:

class Collider
{
    virtual bool isCollidingWith(Collider* c){..}
};

class SphereCollider : public Collider
{
    bool isCollidingWith(Collider* c){..}
};

class BoxCollider : public Collider
{
    bool isCollidingWith(Collider* c){..}
};

class MeshCollider : public Collider
{
    bool isCollidingWith(Collider* c){..}
};

メソッド isCollidingWith は実行時に仮想であるため、ポリモーフィズムにより、それを呼び出しているオブジェクトに基づいて正しいメソッドが呼び出されます (継承されたクラスに isCollidingWith(Collider *c) の実装がある場合、それ以外の場合、継承されたクラスはあまりにも抽象的になります)。

例:

Collider *c1 = new SphereCollider;
Collider *c2 = new BoxCollider;
Collider *c3 = new MeshCollider;

// To check if Sphere is colliding with anything
// This will go to the implementation in SphereCollider
c1->isCollidingWith(c2);
c1->isCollidingWith(c3);

// To check if Box is colliding with anything
// This will go to the implementation in BoxCollider
c2->isCollidingWith(c1);
c2->isCollidingWith(c3);

// To check if Mesh is colliding with anything
// This will go to the implementation in MeshCollider
c3->isCollidingWith(c1);
c3->isCollidingWith(c2);

お役に立てれば。

于 2012-11-05T19:08:06.210 に答える