1

これは非常に具体的な質問であると私は理解しているので、人々が与える答えにこれを行う方法に関する明示的なコードが含まれていると役に立ちます。ありがとう。

私は抽象的な基本クラスShapeを持っています:

class Shape
{
    .....
    virtual bool GetIntersection(Shape* _shape) = 0;
}

class Circle : public Shape  {...}
class Triangle : public Shape {...}

これらの派生クラスは両方ともGetIntersectionをオーバーライドします。

私は持っています:

//main.cpp
....
Shape* shape;
Shape* circle = new Circle;

if(input == 0) shape = new Circle;
else shape = new Triangle;

circle->GetIntersection(shape);

エラーが発生します。

GetIntersectionのパラメーターが使用している派生クラスを基本的に判別する必要があるため、ビジターパターンについて何かを読み、これが問題を解決する方法になると思います。この場合、ビジターパターンを実装する方法を誰かが説明できますか?または、この問題に対する別のより簡単な解決策がある場合。

どんな助けでもいただければ幸いです。

4

4 に答える 4

2

私は今、異なる形状間の衝突で同じ問題に直面しています。

階層 A (訪問者) のクラスが別の階層 B (訪問された要素) のクラスを訪問する必要があるため、訪問者パターンを「そのまま」使用することはできないと思います。ここで、B のクラスは A の抽象化についてのみ知っています。 ( IVisitorなど) B のクラスは A のサブクラス ( VisitedElement1VisitedElement2 ... VisitedElement のサブクラス) について知っています。

私たちの場合、Shape クラスをサブクラスから切り離したまま、Shape を持つ Shape を訪問しようとしているので、Visitor パターンは適用されません。

私が考えることができる最善の解決策は、Shape クラスが、直接または別のインターフェイスを介して、すべてのサブタイプに対して「GetSpecificIntersection」メソッドを宣言することです。

class Shape
{
    .....
public:
    virtual bool GetIntersection(Shape* _shape) = 0;    
protected:
    virtual bool GetSpecificIntersection(Circle* _circle) = 0;
    virtual bool GetSpecificIntersection(Triangle* _triangle) = 0;
}

class Circle
{
    .....
public:
    virtual bool GetIntersection(Shape* _shape);
    {
        return _shape->GetSpecificIntersection(this);
    }
protected:
    virtual bool GetSpecificIntersection(Circle* _circle) { ... }
    virtual bool GetSpecificIntersection(Triangle* _triangle) { ... }
}

class Triangle { /* analog to Circle */ }

したがって、形状の種類ごとに特定の交差メソッドを他の種類の形状に実装する必要があり、Shape クラスは可能なすべての形状に結合されます。私が間違っていなければ、これはOCPに違反しますが、 LSPを維持します。

私が思いついた別のオプションは、「継承よりも構成を優先する」ことであり、次のようなものを作成します。

class Shape
{
    .....
public:
    virtual bool GetIntersection(Shape* _shape)
    {
        return _shape->figure->GetIntersection(this->figure);
    }

private:
    Figure* figure;
}

class Figure
{
    .....
public:
    virtual bool GetIntersection(Figure* _figure) = 0;
protected:
    virtual bool GetSpecificIntersection(Circle* _circle) = 0;
    virtual bool GetSpecificIntersection(Triangle* _triangle) = 0;
}

class Circle
{
    .....
public:
    virtual bool GetIntersection(Figure* _figure)
    {
        return _figure->GetSpecificIntersection(this);
    }
protected:
    virtual bool GetSpecificIntersection(Circle* _circle) { ... }
    virtual bool GetSpecificIntersection(Triangle* _triangle) { ... }
}

class Triangle { /* analog to Circle */ }

以前と同じですが、これを行うことで、Shape クラス (ゲームのクラスで使用されるインターフェイス) を別の "フィギュア" (私はより良い名前を思いつきませんでした) から分離するので、新しいものを追加します。数値が原因でクライアント クラスを再コンパイルする必要さえありません。これは、「Figures」階層でのみOCPに違反し、「Shape」と「Figure」の両方でLSPを保持します。

誰かがダウンキャストを回避しながらこれを行うためのより良い方法を提案できる場合、私は非常に感謝しています:D

于 2012-09-18T20:29:30.710 に答える
2

この質問はこれと重複しているようです: 形状間の衝突をチェックするための設計パターン

ここでは訪問者パターンが使用されており、非常に明確に見えます。秘訣は、各形状 (円、四角など) を他の形状のビジターにすることです。

于 2013-07-09T20:25:38.173 に答える
1

あなたの解決策は正しいです。

最初にバウンディングボックスを取得して、バウンディングボックス間の衝突をチェックすることができます。いずれにせよ、リンゴとオレンジを比較することはできないことに注意してください。したがって、両方の境界ボックスの比較を開始します。

次に、衝突が発生した場合は、個々のポイントを探すことをお勧めします。各形状は、その輪郭の点またはベクトルを返すことができ、衝突があるかどうかを簡単に見つけることができます。ポイントが正方形の内側にあるかどうかを知るのは簡単であるか、ポイントが円の内側にあるかどうかを知ることは、ポイントから中心までの長さが半径よりも大きいことを確認するだけであるなど、速度を上げる方法がいくつかあるかもしれません。

次に、Shape {bool isPointInside(Point p)=0;のようなことを行うことができます。}

これは、個々のポイントをチェックするよりもはるかに高速です。

円のgetIntersectionをオーバーライドして、正方形などを別の方法でチェックすることもできます。Shapeだけでなく。

于 2012-07-08T08:45:35.030 に答える
0

fxdynamic_cast<Circle *>(shape)を使用して、形状が円であるかどうかを確認できます。shape が Circle でない場合は null を返し、それ以外の場合は Circle インスタンスへの有効なポインターを返します。

GetInserection メソッドの 1 つが特定の他の Shape サブタイプと交差する方法を知っている場合は、これを使用します。

それとは別に、Loïc Faure-Lacroix's answerのガイドラインに従ってください。

于 2012-07-09T11:18:11.093 に答える