1

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 Answers2

4

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.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421
  • Hey, right this is certainly in the right direction, it compiles now when the abstract methods are implemented with simple return false; statements. However say i'm not in square.cpp inside of the following method definition `bool Square::detectCollision(Circle *circle) {` `return circle->detectCollision(this);` `}` The error is now that we're pointing to an incomplete class. How is this resolved? – Thomas Anderson Dec 05 '13 at 03:25
  • @ThomasAnderson You need both `#include "square.hpp` and `#include "circle.hpp"` at the top of both implementation files. Each class needs access to every other class. Only the abstract class should see incomplete class declarations. – Potatoswatter Dec 05 '13 at 03:29
1

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;
};
godel9
  • 7,340
  • 1
  • 33
  • 53