开发者

C++ issue concerning inheritance and casting

I am currently working on an amateur physic engine for a school project but I'm stuck because of a C++ issue. The setting is the following :

I have three different classes :

  • RigidBody (abstract)
  • Sphere (inherits from RigidBody)
  • CustomRigidBody (inherits from RigidBody and represents a polyhedra)

I need to check if a collision occurs between a pair of bodies with two eponymous methods. One is used to check for a contact with a Sphere whereas the other is used to check for a contact with a CustomRigidBody. There are several possible scenarii (Sphere/Sphere collision, Sphere/Custom collision, etc...) so these two methods are defined within all of these classes.

In RigidBody, they are abstract :

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

B开发者_Python百科ut not in Sphere :

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

Nor in CustomRigidBody :

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

In my main program, I have a std::vector<RigidBody*> containing pointers to RigidBodies (the superclass) and I need to check for collisions between objects by pair by calling something like :

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;

I was under the impression that C++ would be OK with that but I get the following error message :

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*)

My guess is that it has to do with the fact that the vector of bodies contains pointers to RigidBodies and they are not automatically casted to Sphere* or CustomRigidBody* but I don't know how to fix the issue.

Thank you for your assistance ;)


This problem is solved by Double Dispatch. Essentially, you need to add another overload to RigidBody and its derived classes:

bool isCollidingWith(RigidBody* rb_p) = 0;

In the derived classes, e.g. Sphere, the implementation would look like:

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

This works because the first time isCollidingWith is called (in your loop), the version of isCollidingWith(RigidBody*) from the correct derived class is called (via the virtual method). Then, in Sphere::isCollidingWith(RigidBody*), the correct derived class is used via the virtual method. However, this time, this is a Sphere*, so the overload that is called is the isCollidingWith(Sphere*) version.

In other words:

  1. In your loop:

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

    will call either Sphere::isCollidingWith(RigidBody*) or CustomRigidBody::isCollidingWith(RigidBody*), depending on the actual type of bodies_p[i]. Assuming it is a Sphere, then we get

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

    return rb_p->isCollidingWith(this);
    

    which calls either Sphere::isCollidingWith(Sphere*) or CustomRigidBody::isCollidingWith(Sphere*), depending on the actual type of rb_p.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜