虚拟方法和参数查找

时间:2012-11-05 18:54:44

标签: c++ parameters virtual

我有以下课程:

Collider (abstract based class)
BoxCollider
MeshCollider
SphereCollider

最后3个继承自Collider。

用例是每个碰撞器应该可以检查它是否与任何其他碰撞器发生碰撞。

我想这个调用应该在Collider类中,看起来像:

void Collider::checkCollisionsWithOtherColliders()
{
for(std::vector<Collider*>::iterator it ....)
{
if(this->isCollidingWith(*it){...}
}
}

现在出现了我应该如何定义isCollidingWith

的问题

我想我需要为每对碰撞器定义它,这意味着每个碰撞器类型对于每种类型的碰撞器都应具有此方法的一个版本作为参数,例如在SphereCollider中:

class SphereCollider : public Collider
{

bool isCollidingWith(SphereCollider* c){..}
bool isCollidingWith(BoxCollider* c){..}
bool isCollidingWith(MeshCollider* c){..}

};

为了确保通过Collider基类可以访问这些方法,我需要定义

class Collider
{
virtual bool isCollidingWith(SphereCollider* c){..}
virtual bool isCollidingWith(BoxCollider* c){..}
.. and so on
};

此外,由于调用this->isCollidingWith(*it)只是一个指向Collider而不是派生类的指针,我希望列出的那些虚拟方法的适当方法是在运行时自动获取的。然而,情况似乎并非如此:由于参数只是Collider,它只查找带有Collider *参数的方法。

我能想到的唯一解决方案是在Collider中定义:

bool isCollidingWith(Collider* collider)
{
if (0 != dynamic_cast<SphereCollider*>(collider))
return isCollidingWith(dynamic_cast<SphereCollider*>(collider));
else if (0 != dynamic_cast<BoxCollider*>(collider))
return isCollidingWith(dynamic_cast<BoxCollider*>(collider));
else if ...
}

这不是很优雅。有没有其他(适当的)方法来处理这种情况? 谢谢!

2 个答案:

答案 0 :(得分:4)

这是double dispatch的案例。不会在这里详细说明,因为它已经被广泛使用的成语,即使维基百科页面已经过时,使用该术语的简单谷歌搜索也会产生良好的结果。

答案 1 :(得分:-1)

因为您从Collider继承了BoxCollider,MeshCollider和SphereCollider,所以您不需要创建3种不同的方法来接受每个类的参数。这就是为什么OOP很棒。

您可以使用:

class Collider
{
    virtual bool isCollidingWith(Collider* c){..}
};

class SphereCollider : public Collider
{
    bool isCollidingWith(Collider* c){..}
};

class BoxCollider : public Collider
{
    bool isCollidingWith(Collider* c){..}
};

class MeshCollider : public Collider
{
    bool isCollidingWith(Collider* c){..}
};

因为方法isCollidingWith是虚拟的,在运行时,由于多态性,将根据调用它的对象调用正确的方法(如果继承的类具有isCollidingWith(Collider * c)的实现,否则继承的类也将变得抽象。)

示例:

Collider *c1 = new SphereCollider;
Collider *c2 = new BoxCollider;
Collider *c3 = new MeshCollider;

// To check if Sphere is colliding with anything
// This will go to the implementation in SphereCollider
c1->isCollidingWith(c2);
c1->isCollidingWith(c3);

// To check if Box is colliding with anything
// This will go to the implementation in BoxCollider
c2->isCollidingWith(c1);
c2->isCollidingWith(c3);

// To check if Mesh is colliding with anything
// This will go to the implementation in MeshCollider
c3->isCollidingWith(c1);
c3->isCollidingWith(c2);

希望这有帮助。