0

如果这个问题已经被问过,我很抱歉,但我一直在寻找几个小时,我只找到了类似但不完全相同的问题的答案,而且在我的情况下它们都不起作用。我是一个新手程序员,所以我的代码很可能由于令人畏惧的设计或一个非常简单、愚蠢的错误而无法工作。我有一个替代设计,但我想知道这个设计是否真的不可能,或者我是否只是不正确地实现它。

所以这就是我正在尝试做的事情:我正在编写 2D 碰撞检测代码,它需要同时适用于多边形和圆形。多边形需要能够检测圆形和其他多边形上的碰撞,而圆形需要能够检测多边形和其他圆形上的碰撞。我认为能够将所有可碰撞对象(多边形和圆)放入一个名为“Collidables”的 std::vector 中会很好,而不是为每个类设置一个单独的向量。所以我创建了抽象的 Shape 类,它是 Circle 和 Polygon 的父类,并且拥有虚拟碰撞检测功能。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

这里的想法是,任何 Shape 都应该能够检测到任何其他 Shape 上的碰撞,甚至在调用 detectCollision 函数时甚至不知道它是检测多边形上的碰撞还是圆上的碰撞。想象一下你是一个圆圈,你正在迭代 Collidables std::vector。第一个元素是 Polygon,但你不知道,你只知道你是一个圆,并且你的 detectCollision 函数得到的参数是对 Shape 的引用。所以你告诉 Shape “看,我不知道你是什么,但我是一个圆圈。在这里,我会将自己作为参数传递给你的 detectCollision 函数,这样你就可以将结果返回给我”。因此 Shape 调用了它的虚拟 detectCollision(const &Circle),然后将其传递给 detectCollision(const &

这在只编写 Shape 和 Polygon 类时工作得很好,但是一旦我添加了 Circle 类,我的代码就不再编译了。我得到的错误是:

在 polygon.cpp:1:0 中包含的文件中:polygon.h:在成员函数'virtual Vector* Polygon::detectCollision(const Circle&) const'中:polygon.h:45:78:错误:不完整类型的无效使用' const struct Circle' shape.h:8:7: 错误:'const struct Circle' 的前向声明</p>

我假设这是一个设计问题,因为这里发生了荒谬的循环依赖:Shape取决于它的孩子,因为它的一些虚函数接受孩子作为参数,Polygon取决于Shape(因为它继承自它)和Circle (因为它有一个接受 Circle& 参数的 detectCollision 函数)并且 Circle 取决于 Shape (因为它继承自它)和 Polygon (因为它有一个接受 Polygon& 参数的 detectCollision 函数)。最简单的出路可能就是放弃将多边形和圆放入一个序列容器中的想法,而只是将它们放入两个单独的 std::vectors 中。尽管如此,我还是想知道我的第一个设计是天生不可能,可能但丑陋,还是可靠但实施不正确。

(编辑:戴夫建议的一些代码更改)

编辑,链接到完整源代码,如果有人想要更多信息:https ://github.com/KoenP/medieval-melee-combat-cpp

我只编译文件polygon.cpp、circle.cpp、vector.cpp和line.cpp;test.cpp 当前无关紧要。对于这个错误,向量和线并不是那么重要,不编译它们(只编译多边形和圆)会给出完全相同的错误。我使用的确切命令是“g++ -o test circle.cpp polygon.cpp line.cpp vector.cpp”。

4

1 回答 1

1

这种设计有些常见。使其工作的方法是在标头中转发声明(不要#include)和#include在 cpps 中。你走在正确的轨道上...

circle.h并且polygon.h包括. 从中删除(这是多余的,因为您已经从 include 中获得了它)。那么,在,。而在, . shape.hclass Circle;polygon.hShape.hpolygon.cpp#include "circle.h"circle.cpp#include "polygon.h"

于 2012-11-25T13:22:23.447 回答