Sign in to follow this  
Ubermeowmix

Forward declarations of classes :S

Recommended Posts

Ubermeowmix    969

Looking for a little help with class declarations.

 

If I have the following

#include "myApp.h"
 
int main(int argc, char* argv[])
{
       return myApp::GetInstance()->OnExecute(argc, argv);
}
 
is the forward declaration of Player available in main if placed here?

class Player; //forward declaration
 
class myApp
{
     ///bla
}

 

Share this post


Link to post
Share on other sites
Irlan    4067

In this circunstancy it is generally used to avoid multiple dependencies, and by not including directly in the dependent header (for more intuitive that it looks) it can generate redundant work if you always take this route of defining every time.

 

In your case you'll use the player inside the compilation unit of the application class so you should include directly inside the application header file (assuming the application is a game-state in your case) and avoid including in your .cpp file.

 

If your application is a game wrapper then it needs to know what a player is in your case, so you should include the player header file inside the game header file, otherwise you would doing redundant work.

 

Also, you are using a singleton application instance which can be bad for several reasons (search on the forums).

 

You should have something like:

 

The myApp declare file:

#include "Player.h" 

class myApp //(myGame)
{
     void OnExecute(/*...*/);
     Player player;
}

Then, the entry point:

#include "myApp.h"
 
int main(int argc, char* argv[])
{
       myApp app;
       app.OnExecute(argc, argv);
}
Edited by Irlan

Share this post


Link to post
Share on other sites
Juliean    7077

Actually it is well-adviced to use forward-compilation wherever possible. You can find many sources that explain this in a very detailed matter, for example:

 

http://stackoverflow.com/questions/9906402/should-one-use-forward-declarations-instead-of-includes-wherever-possible

http://stackoverflow.com/questions/10469531/forward-declaration-when-best-to-include-headers

 

The consensus is, that there is no drawback and just benefits from using forward declaration, so you should only include "Player.h" where you are really using a player object (calling methods, etc...) on it.

Share this post


Link to post
Share on other sites
Waterlimon    4398

You should include the forward declaration in all the files that need them. Dont rely on it implicitly being forward declared in some included header file (that just creates a confusing dependency that makes your stuff break if you remove the include, and it wont be as clear that its only a forward declaration of player that is available and not the full declaration).

 

Assuming what you need is the forward declaration only.

Edited by Waterlimon

Share this post


Link to post
Share on other sites
SeanMiddleditch    17565

In your case you'll use the player inside the compilation unit of the application class so you should include directly inside the application header file (assuming the application is a game-state in your case) and avoid including in your .cpp file.


That's terrible advice.

Include Player.h in the source file, not the header. Forward declare everything you possibly can in the headers and only include headers when they're needed, which is often just in the source files. Compilation times scale upward with the amount of source text being pulled in; pulling in headers for a TU that the TU does not need just gives you slower compilation times. Fast iteration for games is critical and when your game is 3 million lines you'll seriously regret not having very strict and clean header inclusion policies from the start. This is one of the huge flaws of C and C++ (though it's far more noticeable in C++ than in C) that'll be fixed when the modules system for C++ finally lands in the spec (maybe by C++17, but probably it'll be a TS around that time and not in the spec until the following C++ revision).

Share this post


Link to post
Share on other sites
Irlan    4067

That's terrible advice.

Include Player.h in the source file, not the header. Forward declare everything you possibly can in the headers and only include headers when they're needed, which is often just in the source files. Compilation times scale upward with the amount of source text being pulled in; pulling in headers for a TU that the TU does not need just gives you slower compilation times. Fast iteration for games is critical and when your game is 3 million lines you'll seriously regret not having very strict and clean header inclusion policies from the start. This is one of the huge flaws of C and C++ (though it's far more noticeable in C++ than in C) that'll be fixed when the modules system for C++ finally lands in the spec (maybe by C++17, but probably it'll be a TS around that time and not in the spec until the following C++ revision).

 

The class design of the OP is obviously well defined:

 

The myApp class needs to know about the Player class. More specifically I said "in your case" because the myApp class (to him) works like a game-state (though it is fair behind a good design because a application doesn't know anything about the player neither the game, but in this case he is explicitly defining this).

 

Look at my example. If the intention of the OP was just to hold a reference to the player he would be using a forward declaration.

 

The OP should include directly when:

#include "Player.h" 

class myApp //(myGame)
{
     void OnExecute(/*...*/);
     Player player;
}

And he should use foward declaration when:

class Player;

class myApp //(myGame)
{
     void OnExecute(/*...*/);
     Player* player;
}

Look that I said that "on the case the myApp class works like a game", so this way he wouldn't have a extreme design issue problem here.

 

You're correct that compilation time increases using foward declaration, but it is not a reason when the class design it is defined, such that the class will create the object, use it, hold a reference, etc.

 

When I was starting I foward declare all my classes in order to de-crease multiple dependency of classes, decrease compilation time, etc, but the truth is that the correct way of not doing this in the wrong way is to think about all classes design first.

Edited by Irlan

Share this post


Link to post
Share on other sites
Phil123    1276


You're correct that compilation time increases using foward declaration, but it is not a reason when the class design it is defined, such that the class will create the object, use it, hold a reference, etc.



When I was starting I foward declare all my classes in order to de-crease multiple dependency of classes, increase compilation time, etc, but the truth is that the correct way of not doing this in the wrong way is to think about all classes design first.

 

Forward declarations reduce compilation time (they don't increase it).  Is that what you meant?

Share this post


Link to post
Share on other sites
SeraphLance    2603

Standard FAQ for inclusion in C (and mostly applicable to C++):

 

I have a function void foo(bar* b); in foo.c that needs stuff in bar.c!

In foo.c, include bar.h.  In foo.h, forward declare bar.  Do it like so:

C:

//C:
typedef struct bar bar;

//C++:
class bar; //or struct bar;

I have a function void foo(bar b); in foo.c that needs stuff in bar.c!

No you don't.  Seriously, don't.

 

Okay, you really need to do this?  Are you sure?

 

Okay.  Then include bar.h in foo.h consider factoring bar.c into a separate .h file that only contains the struct data, and include that file in both bar.c and foo.h.  If you neglect to do this, then don't come crying to anyone when you start to see bizarre bugs (premature hint: You probably have some weird #define in some windows header).

 

Why would I do that when I can just #include "bar.h" in foo.h

Because transitive dependencies make subsequent programmers very, very angry, and some of them have guns.

Edited by SeraphLance

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this