Include guards are a basic necessity of C++ project management, allowing multiple source files to be used — sanely.
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 {};