gpt4 book ai didi

c++ - 接受子引用作为参数的父函数(或三个相互依赖的类的冒险)

转载 作者:行者123 更新时间:2023-11-28 07:52:13 25 4
gpt4 key购买 nike

如果已经问过这个问题,我感到很抱歉,但是我已经找了几个小时,而且我只能找到类似但并非完全相同的问题的答案,而在我看来,这些问题都不起作用。我是一个新手程序员,所以我的代码很可能由于缺乏价值的设计或非常简单,愚蠢的错误而无法正常工作。我有一个替代设计,但是我想知道该设计实际上是不可能的,还是我只是错误地实现了它。

因此,这就是我想要做的事情:我正在编写2D碰撞检测代码,该代码需要同时适用于多边形和圆形。多边形必须能够检测到圆和其他多边形上的碰撞,而圆需要能够检测到多边形和其他圆上的碰撞。我认为能够将所有可碰撞对象(多边形和圆)放入一个称为“ Collidables”的std :: vector中,而不是为每个类都使用单独的矢量,将是一件好事。因此,我创建了抽象的Shape类,该类是Circle和Polygon的父级,并且具有虚拟碰撞检测功能。 Collidables向量将是形状指针的序列。这些类如下所示:

//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),然后将其传递给其子级Polygon的detectCollision(const&Circle),该子项具有实际的工作实现,然后应返回指向交点的指针(或空指针(如果没有交集)。

当仅编写Shape和Polygon类时,此方法运行良好,但是一旦添加Circle类,我的代码将无法编译。我得到的错误是:

在来自polygon.cpp的文件中:1:0:
polygon.h:在成员函数“虚拟矢量* Polygon :: detectCollision(const Circle&)const”中:
gon.h:45:78:错误:无效使用了不完整的类型“ const struct Circle”
shape.h:8:7:错误:正向声明“ const struct Circle”

我假设这是一个设计问题,因为这里存在大量的循环依赖:Shape依赖于其子代,因为其某些虚拟函数接受子代作为参数,Polygon依赖Shape(因为它继承自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多边形.cpp line.cpp vector.cpp”。

最佳答案

这种设计有些普遍。使其工作的方法是在头文件中声明(不要#include),并在cpps中声明#include。你在正确的轨道上...

circle.hpolygon.h中仅包括shape.h。从class Circle;中删除​​polygon.h(这是多余的,因为您已经从包含Shape.h的内容中获得了它)。然后,在polygon.cpp中,在#include "circle.h"中。然后在circle.cpp中,在#include "polygon.h"中。

关于c++ - 接受子引用作为参数的父函数(或三个相互依赖的类的冒险),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13551370/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com