【问题标题】:C++ issue concerning inheritance and casting关于继承和强制转换的 C++ 问题
【发布时间】:2011-02-28 22:42:49
【问题描述】:

我目前正在为一个学校项目开发一个业余物理引擎,但由于 C++ 问题而陷入困境。设置如下:

我有三个不同的课程:

  • 刚体(抽象)
  • 球体(继承自 RigidBody)
  • CustomRigidBody(继承自 RigidBody 并表示多面体)

我需要使用两种同名方法检查一对物体之间是否发生碰撞。一个用于检查与 Sphere 的接触,而另一个用于检查与 CustomRigidBody 的接触。有几种可能的场景(球体/球体碰撞、球体/自定义碰撞等),因此这两种方法都定义在所有这些类中。

在刚体中,它们是抽象的:

virtual bool isCollidingWith(Sphere* s_p) = 0;
virtual bool isCollidingWith(CustomRigidBody* rb_p) = 0;

但不在 Sphere 中:

bool isCollidingWith(Sphere* s_p);
bool isCollidingWith(CustomRigidBody* rb_p);

也不是在 CustomRigidBody 中:

bool isCollidingWith(Sphere* s_p);
bool isCollidingWith(CustomRigidBody* rb_p);

在我的主程序中,我有一个 std::vector<RigidBody*> 包含指向 RigidBody(超类)的指针,我需要通过调用类似的方法逐对检查对象之间的冲突:

for(int i = 1; i < this->bodies_p.size(); ++i)
    for(int j = 0; j < i; ++j)
        if(this->bodies_p[i]->isCollidingWith(this->bodies_p[j]))
            std::cout << " COLLISION BETWEEN " << i << " AND " << j << std::endl;

我的印象是 C++ 可以接受,但我收到以下错误消息:

Engine.cc:35: error: no matching function for call to ‘RigidBody::isCollidingWith(RigidBody*&)’
RigidBody.h:53: note: candidates are: virtual bool RigidBody::isCollidingWith(Sphere*)
RigidBody.h:54: note:                 virtual bool        RigidBody::isCollidingWith(CustomRigidBody*)

我的猜测是它与实体向量包含指向 RigidBody 的指针并且它们不会自动转换为 Sphere* 或 CustomRigidBody* 的事实有关,但我不知道如何解决这个问题。

感谢您的帮助;)

【问题讨论】:

    标签: c++ inheritance casting overloading


    【解决方案1】:

    Double Dispatch 解决了这个问题。本质上,您需要向RigidBody 及其派生类添加另一个重载:

    bool isCollidingWith(RigidBody* rb_p) = 0;
    

    在派生类中,例如Sphere,实现如下:

    bool Sphere::isCollidingWith(RigidBody* rb_p)
    {
        return rb_p->isCollidingWith(this);
    }
    

    这是因为第一次调用isCollidingWith(在您的循环中),来自正确派生类的isCollidingWith(RigidBody*) 版本被调用(通过虚方法)。然后,在Sphere::isCollidingWith(RigidBody*) 中,通过虚方法使用正确的派生类。不过这次thisSphere*,所以调用的重载就是isCollidingWith(Sphere*)版本。

    换句话说:

    1. 在你的循环中:

      this->bodies_p[i]->isCollidingWith(this->bodies_p[j])
      

      将调用Sphere::isCollidingWith(RigidBody*)CustomRigidBody::isCollidingWith(RigidBody*),具体取决于bodies_p[i] 的实际类型。假设它是Sphere,那么我们得到

    2. Sphere::isCollidingWith(RigidBody* rb_p):

      return rb_p->isCollidingWith(this);
      

      调用Sphere::isCollidingWith(Sphere*)CustomRigidBody::isCollidingWith(Sphere*),取决于rb_p 的实际类型。

    【讨论】:

    • 不错的“把戏”。甚至停止添加我的答案,因为这比我的解决方案要好得多。
    • 感谢您的回答和详细的解释!您粘贴的维基百科链接甚至引用物理模拟作为使用双重调度的典型情况之一 =D
    • @RedX:这里也一样。上帝,我喜欢 StackOverflow。 :D
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 2011-11-17
    • 1970-01-01
    相关资源
    最近更新 更多