I have three classes: GameEvents, Physics and GameObject. I have headers for each of them.
GameEventshas onePhysicsand a list ofGameObjects.Physicshas a list ofGameObjects.
Note the circular dependency. I'm trying to achieve that GameObject is able to access or own a Physics object.
If I simply #include "Physics.h" in GameObject, I get
error C2111: 'ClassXXX' : 'class' type redifinition which I understand.
This is where I thought include guards would help so I added an include guard to my Physics.h since that's the header I want to include twice.
This is how it looks
#ifndef PHYSICS_H
#define PHYSICS_H
#include "GameObject.h"
#include <list>
class Physics
{
private:
double gravity;
list<GameObject*> objects;
list<GameObject*>::iterator i;
public:
Physics(void);
void ApplyPhysics(GameObject*);
void UpdatePhysics(int);
bool RectangleIntersect(SDL_Rect, SDL_Rect);
Vector2X CheckCollisions(Vector2X, GameObject*);
};
#endif // PHYSICS_H
But if I #include "Physics.h" in my GameObject.h now like this:
#include "Texture2D.h"
#include "Vector2X.h"
#include <SDL.h>
#include "Physics.h"
class GameObject
{
private:
SDL_Rect collisionBox;
public:
Texture2D texture;
Vector2X position;
double gravityForce;
int weight;
bool isOnGround;
GameObject(void);
GameObject(Texture2D, Vector2X, int);
void UpdateObject(int);
void Draw(SDL_Surface*);
void SetPosition(Vector2X);
SDL_Rect GetCollisionBox();
};
I get multiple issues that don't understand why they're showing up.
If I don't #include "Physics.h" my code runs just fine.
The preprocessor is a program that takes your program, makes some changes (for example include files (#include), macro expansion (#define), and basically everything that starts with
#) and gives the "clean" result to the compiler.The preprocessor works like this when it sees
#include:When you write:
The contents of
some_filealmost literally get copy pasted into the file including it. Now if you have:And:
And:
You get:
Now you can see how
Ais redefined.When you write guards, they become like this:
So now let's look at how
#includes in main would be expanded (this is exactly, like the previous case: copy-paste)Now let's follow the preprocessor and see what "real" code comes out of this. I will go line by line:
Comment. Ignore! Continue:
Is
A_Hdefined? No! Then continue:Ok now
A_His defined. Continue:This is not something for preprocessor, so just leave it be. Continue:
The previous
iffinished here. Continue:Comment. Ignore! Continue:
Is
B_Hdefined? No! Then continue:Ok now
B_His defined. Continue:Is
A_Hdefined? YES! Then ignore until corresponding#endif:Ignore
Ignore
The previous
iffinished here. Continue:This is not something for preprocessor, so just leave it be. Continue:
The previous
iffinished here.That is, after the preprocessor is done with the file, this is what the compiler sees:
So as you can see, anything that can get
#included in the same file twice, whether directly or indirectly needs to be guarded. Since.hfiles are always very likely to be included twice, it is good if you guard ALL your .h files.P.S. Note that you also have circular
#includes. Imagine the preprocessor copy-pasting the code of Physics.h into GameObject.h which sees there is an#include "GameObject.h"which means copyGameObject.hinto itself. When you copy, you again get#include "Pysics.h"and you are stuck in a loop forever. Compilers prevent that, but that means your#includes are half-done.Before saying how to fix this, you should know another thing.
If you have:
Then the compiler needs to know everything about
b, most importantly, what variables it has etc so that it would know how many bytes it should put in place ofbinA.However, if you have:
Then the compiler doesn't really need to know anything about
B(since pointers, regardless of the type have the same size). The only thing it needs to know aboutBis that it exists!So you do something called "forward declaration":
This is very similar to many other things you do in header files such as: