この質問がすでに出されている場合は申し訳ありませんが、私は今何時間も探していて、似ているがまったく同じではない問題に対する答えしか見つけられず、私の場合はどれもうまくいきません。私は初心者のプログラマーなので、クリンジに値する設計か、非常に単純でばかげた間違いが原因で、コードが機能しない可能性があります。私は別のデザインを考えていますが、そのデザインが文字通り不可能なのか、それとも間違って実装しているだけなのかを知りたいのです。
これが私がやろうとしていることです:私は2D衝突検出コードを書いています。これはポリゴンと円の両方で機能する必要があります。ポリゴンは、円や他のポリゴンの衝突を検出できる必要があり、円は、ポリゴンや他の円の衝突を検出できる必要があります。クラスごとに個別のベクトルを設定するのではなく、すべての衝突可能なオブジェクト(ポリゴンと円)を「Collidables」と呼ばれる1つのstd::vectorに配置できると便利だと思いました。そこで、CircleとPolygonの両方の親であり、仮想衝突検出関数を保持する抽象Shapeクラスを作成しました。Collidablesベクトルは、Shapeポインターのシーケンスになります。これらのクラスは次のようになります。
//in shape.h:
#ifndef __SHAPE_H_INCLUDED__
#define __SHAPE_H_INCLUDED__
class Polygon;
class Circle;
class Shape {
//number of functions and variables irrelevant to the issue
//relevant functions, note that Vector with capital 'V' is not std::vector but a class I wrote myself:
virtual Vector* detectCollision(const Shape& Collidable) const = 0;
virtual Vector* detectCollision(const Polygon& Collidable) const = 0;
virtual Vector* detectCollision(const Circle& Collidable) const = 0;
};
#endif
//in polygon.h
#ifndef __POLYGON_H_INCLUDED__
#define __POLYGON_H_INCLUDED__
#include "shape.h"
//edit: deleted #include "circle.h", this is now included in polygon.cpp
//edit: deleted redundant Circle forward declaration
class Polygon: public Shape {
//irrelevant stuff
Vector* detectCollision(const Shape& Collidable) const {return Collidable.detectCollision(*this)};
Vector* detectCollision(const Polygon& Collidable) const;
Vector* detectCollision(const Circle& Collidable) const;
};
#endif
//in circle.h
#ifndef __CIRCLE_H_INCLUDED__
#define __CIRCLE_H_INCLUDED__
#include "shape.h"
//edit: deleted #include "polygon.h", this is now included in circle.cpp
class Circle: public Shape {
//irrelevant stuff
Vector* detectCollision (const Shape& Collidable) const {return Collidable.detectCollision(*this);}
Vector* detectCollision (const Polygon& Collidable) const;
Vector* detectCollision (const Circle& Collidable) const;
};
#endif
ここでの考え方は、detectCollision関数を呼び出したときに、ポリゴンまたは円のどちらで衝突を検出しているかを認識していなくても、他のシェイプでの衝突を検出できる必要があるということです。あなたがサークルであり、Collidables std::vectorを反復処理していると想像してください。最初の要素はポリゴンですが、それはわかりません。自分が円であり、detectCollision関数が取得しているパラメーターがShapeへの参照であることがわかっているだけです。つまり、Shapeは「あなたが何であるかはわかりませんが、私は円です。ここでは、detectCollision関数のパラメーターとして自分自身を渡し、結果を返すことができるようにします」と言います。そのため、Shapeは仮想のdetectCollision(const&Circle)を呼び出し、それがdetectCollision(const&Circle)に渡されます。
これは、ShapeクラスとPolygonクラスのみが記述されている場合は正常に機能しましたが、Circleクラスを追加すると、コードはコンパイルされなくなりました。私が得ているエラーは次のとおりです。
PNGからインクルードされたファイル内:polygon.cpp:1:0:polygon.h:メンバー関数内'virtual Vector * Polygon :: detectCollision(const Circle&)const':polygon.h:45:78:エラー:不完全なタイプの無効な使用' const struct Circle'shape.h:8:7:エラー:' conststructCircle'の前方宣言</p>
ここで行われている循環依存関係の量がばかげているため、これは設計上の問題だと思います。仮想関数の一部は子をパラメーターとして受け入れるため、Shapeは子に依存し、PolygonはShape(継承するため)およびCircleに依存します。 (Circle&パラメーターを受け入れるdetectCollision関数があるため)CircleはShape(継承するため)とPolygon(Polygon&パラメーターを受け入れるdetectCollision関数があるため)に依存します。最も簡単な方法は、ポリゴンと円を1つのシーケンスコンテナに入れて、2つの別々のstd::vectorsに入れるというアイデアをあきらめることです。それでも、私の最初の設計が本質的に不可能であるか、可能であるが醜いのか、それとも堅実であるが正しく実装されていないのかを知りたいと思います。
(編集:Daveによって提案されたいくつかのコード変更)
編集、完全なソースへのリンク、誰かがより多くの情報を必要とする場合:https ://github.com/KoenP/medieval-melee-combat-cpp
私はファイルpolygon.cpp、circle.cpp、vector.cpp、line.cppのみをコンパイルしています。test.cppは現在無関係です。このエラーでは、ベクトルと線はそれほど重要ではありません。コンパイルしないと(ポリゴンと円をコンパイルするだけで)、まったく同じエラーが発生します。私が使用している正確なコマンドは、「g ++ -otestcircle.cpppolygon.cppline.cppvector.cpp」です。