複数発送歓迎!基本的に、複数のオブジェクトの実行時の型に関して仮想的なメソッドを求めています。あなたの場合、重複についてテストされている2つの形状の型です。
C++ でダブル ディスパッチを実装するには、いくつかの一般的な方法があります。たとえば、訪問者パターンを使用したり、 RTTIに基づいてマップを作成したりできます。どちらを選択するかはあなた次第です。
訪問者パターンを使用することにした場合はShape
、訪問メソッドを追加して「訪問可能」にします。
訪問者ベースのアプローチの例を次に示します。確かにかなり冗長ですが、複雑なタスクにも対応しているため、多くのコードが必要になるのは当然です。以下の例では、データ メンバーを持たない 2 つの図形と、印刷以外のことを何も行わないメソッドのみを最小限に抑えています。ただし、これで開始するには十分なはずです。
#include <iostream>
using namespace std;
class ShapeVisitor;
struct Shape {
virtual void accept(ShapeVisitor& v) = 0;
virtual bool overlaps(Shape& other) = 0;
};
class Circle;
class Square;
struct ShapeVisitor {
virtual void visitCircle(Circle& c) = 0;
virtual void visitSquare(Square& s) = 0;
};
// These three methods do the actual work
bool checkOverlap(Square& s, Circle& c) {
cout << "Checking if square overlaps circle" << endl;
return false;
}
bool checkOverlap(Square& a, Square& b) {
cout << "Checking if square overlaps square" << endl;
return false;
}
bool checkOverlap(Circle& a, Circle& b) {
cout << "Checking if circle overlaps circle" << endl;
return false;
}
class Square : public Shape {
struct OverlapVisitor : public ShapeVisitor {
OverlapVisitor(Square& _my) : result(false), my(_my) {}
virtual void visitCircle(Circle& c) {
result = checkOverlap(my, c);
}
virtual void visitSquare(Square& s) {
result = checkOverlap(my, s);
}
bool result;
Square& my;
};
public:
virtual void accept(ShapeVisitor& v) {
v.visitSquare(*this);
}
virtual bool overlaps(Shape& other) {
OverlapVisitor v(*this);
other.accept(v);
return v.result;
}
};
class Circle : public Shape {
struct OverlapVisitor : public ShapeVisitor {
OverlapVisitor(Circle& _my) : result(false), my(_my) {}
virtual void visitCircle(Circle& c) {
result = checkOverlap(my, c);
}
virtual void visitSquare(Square& s) {
// Important: note how I switched the order of arguments
// compared to Square::OverlapVisitor! There is only one
// square/circle overlap function checker, and it expects
// the square to be the first argument.
result = checkOverlap(s, my);
}
bool result;
Circle& my;
};
public:
virtual void accept(ShapeVisitor& v) {
v.visitCircle(*this);
}
virtual bool overlaps(Shape& other) {
OverlapVisitor v(*this);
other.accept(v);
return v.result;
}
};
これが ideone で実行中のデモです。
RTTI アプローチでは、 where チェッカーを への 2 つのポインターを受け取り、形状が重なるかどうかに応じてorを返すmap<pair<type_info,type_info>,checker>
関数の型にすることができます。オブジェクト型のペアごとにそのような関数を 1 つ作成し、予想されるパラメーター型に基づいてこれらの関数へのポインターをマップに入力し、実行時にこのマップを使用して目的の関数を呼び出します。Shape
true
false
type_info
More Effects C++ bookの Item 31では、これら両方のアプローチについて詳細に説明し、いくつかの優れた例を示しています。実際、この本で説明されているゲーム オブジェクトのペア間の衝突を検出するユース ケースは、あなたが実装しているものと似ています。