==编辑3 ==
最后,我刚刚向checkIntersect(Shape)
添加了checkIntersectSpecific(Circle/Polygon/Triangle)
和Shape
个抽象方法,并让它们调用我已经实现的免费(非成员)函数并在一个地方,使用一些预处理器和标题技巧来保存自己一些重复的代码,以防我需要添加其他子类。为了完成起见,我会标记杰弗弗里的答案,因为他是最接近我所做的,但是我很感谢你们所有人向我展示了一些我实际上不了解的很酷的东西(功能模板)并将我链接到另外两个问题也提出访客/双重发送作为解决方案。
虽然我不得不说,但我希望我们很快就会看到C ++中的多方法。
==编辑OVER ==
所以我有一个基类Shape
及其子项:Triangle
,Polygon
,Circle
和Vector
以及10个不同对的静态函数所述孩子检查他们是否相交。
我还有一个GameObject类,它有一个Shape*
成员,我想实现碰撞检测。出于这个原因,我需要像bool checkIntersection(Shape*, Shape*)
这样的东西来处理各种形状。
我最初的想法是只有(Shape, Shape)
函数并以某种方式检查Shapes的类型,然后调用适当的交集检查函数,但我读到这称为RTTI,通常被认为是坏的。我读到了访客和双重调度,但我看到的方式,这些并没有真正解决我的问题。如果我错了,请随时纠正我。无论如何,现在我被卡住了。我几乎没有想到这个标题。
EDIT2:它不一定需要像这样设计。我只需要稍微易于维护,如果我决定稍后再添加另一个子类,则最好不需要更新每个Shape子类。
编辑: 澄清一下,这就是我想要完成的事情:
class Shape {...} //this is an abstract class
class Circle : public Shape {...}
class Triangle : public Shape {...}
class Polygon : public Shape {...}
bool checkIntersection(const Shape &s1, const Shape &s2)
{
//Do some magic and call the right function
}
bool checkIntersection(const Circle &c, const Triangle &t) {..check...}
bool checkIntersection(const Circle &c, const Polygon &p) {...check...}
//and the rest of the functions for the different combinations
class GameObject
{
Shape * shape;//Shape is abstract
bool collidesWith(const GameObject& obj)
{
return checkIntersection(*this->shape, *obj.shape);
}
}
答案 0 :(得分:1)
另一种选择是使用模板。由于您可能需要为所有可能的Shape组合实现交集逻辑,因此您可以执行以下操作:
#include <iostream>
using namespace std;
struct ShapeA {};
struct ShapeB {};
struct ShapeC {};
struct ShapeD {};
template <class A, class B>
bool checkIntersection(A& a, B& b)
{
// intersection Logic (generic)
}
// you can implement specific logic for some intersections
template <>
bool checkIntersection<ShapeA,ShapeB>(ShapeA& a, ShapeB& b)
{
cout << "Intersection for ShapeA and ShapeB" << endl;
}
int main() {
// your code goes here
ShapeA a;
ShapeB b;
ShapeC c;
ShapeD d;
checkIntersection(a,b);
checkIntersection(a,a);
checkIntersection(c,b);
// and so on. The beauty here is the function guessing the input parameter types
return 0;
}
我在这种方法中看到的一些优点是: 1)没有类型检查(没有强制转换,没有开关/案例代码,遵循开/关原则)。 2)你仍然可以将它与继承结合起来。
模板当然有缺点,这种情况没有灵丹妙药,但在这种情况下,当你可以让模板函数担心参数类型时,我发现它特别好看:)
我希望它有所帮助!
答案 1 :(得分:1)
您正在尝试删除类型,然后使用该类型。这没什么意义。只需使用重载。不需要在那里使用基类:
checkIntersection(const& Triangle, const& Polygon) { ... }
checkIntersection(const& Triangle, const& Circle) { ... }
// ...
checkIntersection(const& Polygon p, const& Triangle t) {
return checkIntersection(t, p);
}
// ...
答案 2 :(得分:-1)
不同的想法:使用Shape enum
enum class ShapeType{
Triangle ,
Circle
}
现在,每个形状都将ShapeType作为内部成员变量
class Shape{
private:
ShapeType m_ShapeType;
}
每个形状都会在其构造函数中将变量初始化为正确的类型。
现在在Shape中创建一个返回ShapeType的函数:
ShapeType getType (){
return m_ShapeType;
}
Shape :: checkIntrsection (Shape* , Shape*)
中的只需让每个Shape *返回类型,你知道类型。