Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Forward declaration & circular dependency

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?

like image 808
Oracular Avatar asked May 28 '13 22:05

Oracular


People also ask

How does forward declaration work?

Forward Declaration refers to the beforehand declaration of the syntax or signature of an identifier, variable, function, class, etc. prior to its usage (done later in the program). In C++, Forward declarations are usually used for Classes.

When can you use forward declaration?

You will usually want to use forward declaration in a classes header file when you want to use the other type (class) as a member of the class. You can not use the forward-declared classes methods in the header file because C++ does not know the definition of that class at that point yet.

Should I use forward declaration or include?

As the name itself implies, forward declaration is just a Declaration and not a definition. So, you will declare saying the compiler that it is a class and I just declaring it here and will provide you the definition when am gonna use it. So, normally you forward declare in the Header file and #include in the .

How do you fix a forward declaration in C++?

To solve this, you can forward-declare the parts you need in one of the files and leave the #include out of that file. Hmm... the declaration of Car is required here as Wheel has a pointer to a Car , but Car. h can't be included here as it would result in a compiler error.


1 Answers

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);
}
like image 63
John Kugelman Avatar answered Sep 21 '22 06:09

John Kugelman