在两个派生类之间执行专用代码

时间:2017-07-19 23:32:20

标签: c++ oop

在游戏的任意物理引擎中,存在“Shape”超类及其派生的子类,例如“AABB”或“Triangle”。每对之间的碰撞检测方法是唯一的,例如AABB-Sphere测试显然不同于Triangle-AABB测试。如果我有两个形状集合,我希望检查它们之间的一些碰撞:

// somewhere in the program
Shape* shape_a;
Shape* shape_b;

....

if (shape_a->intersects(shape_b)) {
    // do something
}

如何执行特定的碰撞检查(例如AABB-ABBB或AABB-Sphere)?例如,如果shape_a指向派生的Triangle对象,并且shape_b执行派生的AABB对象,那么相交函数如何正确地比较Triangle和AABB对象?我当前的实现如下,但它不会编译,因为创建了一个包含循环(可能是由于糟糕的OOP实践)。

Shape.h

#include "AABB.h"
#include "triangle.h"

class Shape {
public:
    virtual bool intersects(Shape* shape) = 0;
    virtual bool intersects(AABB aabb) = 0;
    virtual bool intersects(Triangle tri) = 0;
}

AABB.h

#include "shape.h"

class AABB : public Shape {
    // overriden functions
    bool intersects(Shape* shape);
    bool intersects(AABB aabb); // aabb-aabb
    bool intersects(Triangle tri); // aabb-tri
}

triangle.h

#include "shape.h"

class Triangle : public Shape {
    // overriden functions
    bool intersects(Shape* shape);
    bool intersects(AABB aabb); // tri-aabb
    bool intersects(Triangle tri); // tri-tri
}

交叉(Shape * shape)函数的实现如下所示:

// in AABB.cpp
bool intersects(Shape* shape) {
     return shape.intersects(*this); // where *this is an AABB object
}

当然,我想避免代码重复:tri-aabb测试与aabb-tri测试相同。也许我正在编写基本上有缺陷的代码并且是糟糕的OOP实践。在任何情况下,我都很感激这个问题的任何帮助!

1 个答案:

答案 0 :(得分:0)

要避免include循环,您只需在shape.h中向前声明AABBTriangle类:

class AABB;
class Triangle;

为避免基于参数顺序重复代码,您可以为每个重载对设置一个具有规范顺序的单独函数,并使用成员函数中的不同顺序调用它:

bool intersects( AABB *, Triangle * );

AABB::intersects( Triangle *t ) { return intersects( this, t ); }
Triangle::intersects( AABB *b ) { return intersects( b, this ); }