Reputation: 141
I am getting crazy, cryptic compiler errors when trying to build my solution on VS2010. I'm really having a hard time understanding how these includes work.
Game.cpp
Game.h
Deck.cpp
Deck.h
Card.h
// Game.cpp
#include "Game.h"
All good. Now I need to create a new deck:
// Game.h
private:
static Deck _deck;
Well then I need to include the Deck.h so it knows what it is:
// Game.h
#include "Deck.h"
class Game {
private:
Deck _deck;
}
Okay, thats fine. But now I need to use the _deck in Game.cpp
// Game.cpp
#include "Game.h"
Deck Game::_deck;
void Shuffle(void)
{
_deck = Deck();
_deck.Shuffle();
}
But I get an error saying that "Deck is undefined". But since Game.cpp includes Game.h should Game.h include Deck.h?
If I add Deck.h to Game.cpp I get:
"Uses undefinied class Deck Game.cpp"
and
"Deck class redeclaration Deck.h"
I don't understand this at all...
Upvotes: 2
Views: 2361
Reputation: 5065
#include
is part of the preprocessor phase that runs prior to your compiler and basically performs a substitution of the text.
The problem you describe has to do with translation units. Basically you can think of a source file (.c, .cpp, .inl, etc.) to be different than a header file (.h, .hpp) in the fact that each source file defines a translation unit that the compiler can operate on. The source file is essentially composed of all the logic in the file plus all of the includes it either directly or indirectly refers to.
The compiler will build object files out of each translation unit and then it is the job of the linker to put them all together into a library or executable binary. Logic inside of other source files is not immediately available to any other source file or header until linking time.
The easiest thing to remember is that header files are defining your interface and source files are defining your implementation. You want your header files to be as light as possible and free from as much of the implementation details as you can to increase compile time speed and loosen coupling between objects. You do this by relying on forward declarations in header files and attempting to keep as few .h references inside of other header files and instead moving those to the source files.
Many modern languages mix the two concepts of interface and implementation and with the power of newer IDEs this isn't much of a problem. I still look back and appreciate the separation in C++, however, as this approach is much more explicit. A client of a well written class should be able to ignore the implementation details and thus the header is all they should need to see to use the class. When you are dealing with libraries in C++ this is often the case as you may only have access to header files.
Upvotes: 1
Reputation: 258608
You have a circular include. Luckily for you, a static
member doesn't require a full definition when declared, so you can your include in Game.h with a forward declaration:
// Game.h
class Deck;
//....
private:
static Deck _deck;
Upvotes: 1
Reputation: 8885
You should see this stackoverflow question that explains include guards
Why are #ifndef and #define used in C++ header files?
Upvotes: 2