C++ Polymorphic Circular depenencies with double dispatch

427 views Asked by At

So, I'm having a big issue with circular dependency. My Square.h and Circle.h classes both inherit Shape.h, and use double dispatch in order to try and detect collision between the two. My classes are currently setup in the following sort of fashion

Shape.h

class Shape {
public:
    virtual bool detectCollision(Shape* obj) = 0;
    virtual bool detectCollision(Square* obj) = 0;
    virtual bool detectCollision(Circle* obj) = 0;

Square.h

#include "shape.h"
class Square : public Shape {
public:
    bool detectCollision(Shape* obj);
    bool detectCollision(Square* obj);
    bool detectCollision(Circle* obj);

Circle.h

#include "shape.h"
class Circle: public Shape {
public:
    bool detectCollision(Shape* obj);
    bool detectCollision(Square* obj);
    bool detectCollision(Circle* obj);

Essentially i'm wanting to be able to do something similar to

Circle circle;
Square square;
Square square2;

circle.detectCollision(&square);
square.detectCollision(&square2);

But i'm running into a few errors when I try to compile this. Obviously including "Circle.h", inside of Square.h is going to cause a circular loop that won't execute. Can anybody suggest a good solution for this issue?

Obviously collision detection between two squares and a circle and a square is different, so I need to somehow overload those methods. I thought this would be a good solution, any pointers?

Errors (These compile errors are the same or Square.cpp and Shape.cpp):

Circle.cpp
    shape.h(12): error C2061: syntax error : identifier 'Square'
    shape.h(13): error C2061: syntax error : identifier 'Circle'
    shape.h(13): error C2535: 'bool Shape::detectCollision(void)' : member function already defined or declared
2

There are 2 answers

2
Potatoswatter On BEST ANSWER

You simply need forward declarations.

class Square; // Declarations, not definitions.
class Circle;

class Shape {
    // At this point, Square * and Circle * are already well-defined types.
    // Square and Circle are incomplete classes though and cannot yet be used.

I would suggest using references instead of pointers, since nullptr is not a viable argument, and const-qualifying everything since collision detection does not require modifying anything.

0
godel9 On

You need to forward declare the classes:

class Square;
class Circle;

class Shape {
public:
    virtual bool detectCollision(Shape* obj) = 0;
    virtual bool detectCollision(Square* obj) = 0;
    virtual bool detectCollision(Circle* obj) = 0;
};