Include Guards

Include guards are a basic necessity of C++ project management, allowing multiple source files to be used — sanely.

Table of Contents

Motivation

The basic problem comes when two headers have a mutual dependancy on another header:

//base.hpp
class base {};
//derived1.hpp
#include "base.hpp"
class derived1 : base {};
//derived2.hpp
#include "base.hpp"
class derived2 : base {};
//main.cpp
#include "derived1.hpp"
#include "derived2.hpp"
 
int main() {
    base a;
    derived1 b;
    derived2 c;
}

This gives us an error. On MSVC 8.0, the error is:

base.hpp(2) : error C2011: 'base' : 'class' type redefinition

Include guards allow us to avoid this problem.

Usage

The usage of include guards is rather simple — every header file (.h/.hpp) gets a unique identifier. I use IG_PROJECT_NAME_FILE_NAME, IG standing for Include Guard, and PROJECT_NAME/FILE_NAME being replaced with, well, it should be obvious. Like any #define, ALLCAPS should be used, and no special symbols — this means ALLCAPSing your filenames, and using underscore instead of dot and slash. This identifier is used to see if the file has already been #included, and to ignore the rest of the file if it has been. Here's how it works:

#ifndef IG_PROJECT_NAME_FILE_NAME // If we haven't been #included before...
#define IG_PROJECT_NAME_FILE_NAME // ...now we have...
 
*rest of the code* // this gets ignored if we were already #included
 
#endif //ndef IG_PROJECT_NAME_FILE_NAME // and now we're done!

Applied to the above example:

//base.hpp
#ifndef IG_GUARD_EXAMPLE_BASE
#define IG_GUARD_EXAMPLE_BASE
 
class base {};
 
#endif //ndef IG_GUARD_EXAMPLE_BASE
//derived1.hpp
 
#ifndef IG_GUARD_EXAMPLE_DERIVED1
#define IG_GUARD_EXAMPLE_DERIVED1
#include "base.hpp"
 
class derived1 : base {};
 
#endif //ndef IG_GUARD_EXAMPLE_DERIVED1
//derived2.hpp
 
#ifndef IG_GUARD_EXAMPLE_DERIVED2
#define IG_GUARD_EXAMPLE_DERIVED2
#include "base.hpp"
 
class derived2 : base {};
 
#endif //ndef IG_GUARD_EXAMPLE_DERIVED2
//main.cpp -- no include guards for .cpp files like this one
//    (since they should never be #included for any reason whatsoever)
#include "derived1.hpp"
#include "derived2.hpp"
 
int main() {
    base a;
    derived1 b;
    derived2 c;
}

The code will now compile without error (and run, although the program does nothing).

Rationale

To realize what the problem is, we first need to realize that #include, part of the C++ preprocessor step, is dumb — in effect, it just copies the text from the other file and pastes it in it's place. So let's see what the preprocessed file looks like when compiling main.cpp.

After the #includes in main.cpp have been applied:

#include "base.hpp"
class derived1 : base {};
#include "base.hpp"
class derived2 : base {};
 
int main() {
    base a;
    derived1 b;
    derived2 c;
}

After the others have been applied:

class base {};
class derived1 : base {};
class base {};
class derived2 : base {};
 
int main() {
    base a;
    derived1 b;
    derived2 c;
}

The problem is pretty self evident:

class base {}; //<---------------- base defined here...
class derived1 : base {};
class base {}; //<---------------- ...and defined again here!
class derived2 : base {};

The include guards end up removing the second, resulting in:

class base {}; //<---------------- base defined here...
class derived1 : base {}; //______ ...but removed from here!
class derived2 : base {};