12

I've got two classes, Entity and Level. Both need to access methods of one another. Therefore, using #include, the issue of circular dependencies arises. Therefore to avoid this, I attempted to forward declare Level in Entity.h:

class Level { };

However, as Entity needs access to methods in Level, it cannot access such methods, since it does not know they exist. Is there a way to resolve this without re-declaring the majority of Level in Entity?

Bernhard Barker
  • 54,589
  • 14
  • 104
  • 138
Oracular
  • 367
  • 1
  • 4
  • 13

2 Answers2

11

A proper forward declaration is simply:

class Level;

Note the lack of curly braces. This tells the compiler that there's a class named Level, but nothing about the contents of it. You can then use pointers (Level *) and references (Level &) to this undefined class freely.

Note that you cannot directly instantiate Level since the compiler needs to know the class's size to create variables.

class Level;

class Entity
{
    Level &level;  // legal
    Level level;   // illegal
};

To be able to use Level in Entity's methods, you should ideally define Level's methods in a separate .cpp file and only declare them in the header. Separating declarations from definitions is a C++ best practice.

// entity.h

class Level;

class Entity
{
    void changeLevel(Level &);
};


// entity.cpp

#include "level.h"
#include "entity.h"

void Entity::changeLevel(Level &level)
{
    level.loadEntity(*this);
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 1
    This solves some of my issues, however when I attempt to use methods of Level in Entity, i get an "incomplete type not allowed" error. Edit: Despite your edit, my pointers still will not allow me to access the methods, claiming it is an incomplete type. – Oracular May 28 '13 at 22:31
  • I actually have nearly exactly what you have there; the function is declared in Entity.h, taking a parameter of Level &. In the .cpp file, where I define the function, the line where you have "level.loadEntity(*this);" underlines level in red, and shows the "incomplete type not allowed" error. – Oracular May 28 '13 at 22:38
  • 2
    Edit: I had to #include "level.h" in entity.cpp. I figured if I could not include it in the entity.h file, it could not be included in the .cpp file for the same reason. Including this fixed the issue. Thanks! – Oracular May 28 '13 at 22:43
1

you two options:

  1. use pointers in which case your forward declares should be ok.
  2. inline the methods of one class, in which case if you include the .h file you can use the methods of the other.

Personally I would go down path number 1, it's cleaner and allows better access. I use a lot of shared_ptr so I do not have to worry about deletes...

Entity.h:
class Level;
class Entity {

private:
   Level* m_pLevel;

public:
   bool  CheckLevel ();
   bool WasItThere();


Level.h

class Entity;
class Level {

private:
   Entity* m_pEntity;



    public:
       public bool CheckMyStuff();
       public bool CheckItOut() { return m_pEntity->WasItThere();}
}


Entity.cpp

#include "Level.h"

bool Entity::CheckLevel () {
  return true;
}


bool Entity::CheckLevel() {
   return m_pLevel->CheckMyStuff();
}

bool Entity::WasItThere() {
   return true;
}



Level.cpp

bool Level::CheckMyStuff() { 
    return true;
}

bool Level::CheckItOut() { 
    return m_pEntity->WasItThere();
}
Dory Zidon
  • 10,497
  • 2
  • 25
  • 39