Search code examples
c++sdl

C++ Include Guard Weird Behaviour?


I'm working on my SDL game project using Ubuntu.
I've created a header ( declaration ) and its cpp file ( definition ).
And something started bugging me, please shed some light.

What Works & What I Have :

( All 3 files are under the same folder )

movement.h:

#include <SDL2/SDL.h>
class Movement{ ...... };`

movement.cpp:

    #include <SDL2/SDL.h>
    #include "movement.h"
    // Every Definition

main.cpp:

    #include <SDL2/SDL.h>
    #include "movement.h"
    ...... // contents

Compile:

$ g++ main.cpp movement.cpp movement.h -lSDL2 -lSDL2_image

What DOESN'T Work( with include guard ):

( I only changed movement.cpp, the rest stays the same )

movement.cpp:

#include <SDL2/SDL.h>
#ifndef MOVEMENT_H
#define MOVEMENT_H
...... // contents
#endif

Error: Compiler complains that it can't recognize anything from movement.h
For example:

......
movement.cpp: At global scope:
movement.cpp:73:6: error: ‘Movement’ has not been declared
......

My Questions:

1) Why my include guard ( in movement.cpp ) doesn't work ?
I supposed it would include "movement.h" ( when there isn't one already ).

*Using include guard for <SDL2/SDL.h> doesn't work either( the compiler gives "not been declared" error ). The code looks like this:

#ifndef SDL2_SDL_H
#define SDL2_SDL_H
......
#endif

2) Why <SDL2/SDL.h> doesn't need an include guard ?
Apparently there's one included in movement.h and another in main.cpp. Shouldn't there be a double inclusion error ?


Solution

  • movement.h:

    #include <SDL2/SDL.h>
    class Movement{ ...... };
    

    Headers may be included into multiple files. You should use a header guard, which seems to be missing from this header.


    1) Why my include guard ( in movement.cpp ) doesn't work ?

    movement.cpp:

    #include <SDL2/SDL.h>
    #ifndef MOVEMENT_H
    #define MOVEMENT_H
    

    Source files should never be included into other files, so you shouldn't need an include guard.


    Compile:

    $ g++ main.cpp movement.cpp movement.h -lSDL2 -lSDL2_image
                                ^^^^^^^^^^
    

    Header files don't need to be compiled.


    2) Why <SDL2/SDL.h> doesn't need an include guard ?

    SDL2/SDL.h does have an include guard:

    #ifndef SDL_h_
    #define SDL_h_
    

    Apparently there's one included in movement.h and another in main.cpp. Shouldn't there be a double inclusion error ?

    No. The header guard removes the latter inclusion. That is what header guard is for.

    P.S. Header guard is only required if the header has definitions. A header which only has declarations doesn't need to have a guard. However, it's easier to simply use a header guard in all headers than to try to figure out which of the headers they are not needed for.