Two common questions about include guards:
FIRST QUESTION:
Why aren't include guards protecting my header files from mutual, recursive inclusion? I keep getting errors about non-existing symbols which are obviously there or even weirder syntax errors every time I write something like the following:
"a.h"
#ifndef A_H #define A_H #include "b.h" ... #endif // A_H
"b.h"
#ifndef B_H #define B_H #include "a.h" ... #endif // B_H
"main.cpp"
#include "a.h" int main() { ... }
Why do I get errors compiling "main.cpp"? What do I need to do to solve my problem?
SECOND QUESTION:
Why aren't include guards preventing multiple definitions? For instance, when my project contains two files that include the same header, sometimes the linker complains about some symbol being defined multiple times. For instance:
"header.h"
#ifndef HEADER_H #define HEADER_H int f() { return 0; } #endif // HEADER_H
"source1.cpp"
#include "header.h" ...
"source2.cpp"
#include "header.h" ...
Why is this happening? What do I need to do to solve my problem?
They are.
What they are not helping with is dependencies between the definitions of data structures in mutually-including headers. To see what this means, let's start with a basic scenario and see why include guards do help with mutual inclusions.
Suppose your mutually including
a.h
andb.h
header files have trivial content, i.e. the ellipses in the code sections from the question's text are replaced with the empty string. In this situation, yourmain.cpp
will happily compile. And this is only thanks to your include guards!If you're not convinced, try removing them:
You'll notice that the compiler will report a failure when it reaches the inclusion depth limit. This limit is implementation-specific. Per Paragraph 16.2/6 of the C++11 Standard:
So what's going on?
main.cpp
, the preprocessor will meet the directive#include "a.h"
. This directive tells the preprocessor to process the header filea.h
, take the result of that processing, and replace the string#include "a.h"
with that result;a.h
, the preprocessor will meet the directive#include "b.h"
, and the same mechanism applies: the preprocessor shall process the header fileb.h
, take the result of its processing, and replace the#include
directive with that result;b.h
, the directive#include "a.h"
will tell the preprocessor to processa.h
and replace that directive with the result;a.h
again, will meet the#include "b.h"
directive again, and this will set up a potentially infinite recursive process. When reaching the critical nesting level, the compiler will report an error.When include guards are present, however, no infinite recursion will be set up in step 4. Let's see why:
main.cpp
, the preprocessor will meet the directive#include "a.h"
. This tells the preprocessor to process the header filea.h
, take the result of that processing, and replace the string#include "a.h"
with that result;a.h
, the preprocessor will meet the directive#ifndef A_H
. Since the macroA_H
has not yet been defined, it will keep processing the following text. The subsequent directive (#defines A_H
) defines the macroA_H
. Then, the preprocessor will meet the directive#include "b.h"
: the preprocessor shall now process the header fileb.h
, take the result of its processing, and replace the#include
directive with that result;b.h
, the preprocessor will meet the directive#ifndef B_H
. Since the macroB_H
has not yet been defined, it will keep processing the following text. The subsequent directive (#defines B_H
) defines the macroB_H
. Then, the directive#include "a.h"
will tell the preprocessor to processa.h
and replace the#include
directive inb.h
with the result of preprocessinga.h
;a.h
again, and meet the#ifndef A_H
directive again. However, during previous preprocessing, macroA_H
has been defined. Therefore, the compiler will skip the following text this time until the matching#endif
directive is found, and the output of this processing is the empty string (supposing nothing follows the#endif
directive, of course). The preprocessor will therefore replace the#include "a.h"
directive inb.h
with the empty string, and will trace back the execution until it replaces the original#include
directive inmain.cpp
.Thus, include guards do protect against mutual inclusion. However, they can't help with dependencies between the definitions of your classes in mutually-including files:
Given the above headers,
main.cpp
will not compile.To see what's going on, it is enough to go through steps 1-4 again.
It is easy to see that the first three steps and most of the fourth step are unaffected by this change (just read through them to get convinced). However, something different happens at the end of step 4: after replacing the
#include "a.h"
directive inb.h
with the empty string, the preprocessor will start parsing the content ofb.h
and, in particular, the definition ofB
. Unfortunately, the definition ofB
mentions classA
, which has never been met before exactly because of the inclusion guards!Declaring a member variable of a type which has not been previously declared is, of course, an error, and the compiler will politely point that out.
You need forward declarations.
In fact, the definition of class
A
is not required in order to define classB
, because a pointer toA
is being declared as a member variable, and not an object of typeA
. Since pointers have fixed size, the compiler won't need to know the exact layout ofA
nor to compute its size in order to properly define classB
. Hence, it is enough to forward-declare classA
inb.h
and make the compiler aware of its existence:Your
main.cpp
will now certainly compile. A couple of remarks:#include
directive with a forward declaration inb.h
was enough to effectively express the dependency ofB
onA
: using forward declarations whenever possible/practical is also considered to be a good programming practice, because it helps avoiding unnecessary inclusions, thus reducing the overall compilation time. However, after eliminating the mutual inclusion,main.cpp
will have to be modified to#include
botha.h
andb.h
(if the latter is needed at all), becauseb.h
is no more indirectly#include
d througha.h
;A
is enough for the compiler to declare pointers to that class (or to use it in any other context where incomplete types are acceptable), dereferencing pointers toA
(for instance to invoke a member function) or computing its size are illegal operations on incomplete types: if that is needed, the full definition ofA
needs to be available to the compiler, which means the header file that defines it must be included. This is why class definitions and the implementation of their member functions are usually split into a header file and an implementation file for that class (class templates are an exception to this rule): implementation files, which are never#include
d by other files in the project, can safely#include
all the necessary headers to make definitions visible. Header files, on the other hand, won't#include
other header files unless they really need to do so (for instance, to make the definition of a base class visible), and will use forward-declarations whenever possible/practical.They are.
What they are not protecting you from is multiple definitions in separate translation units. This is also explained in this Q&A on StackOverflow.
Too see that, try removing the include guards and compiling the following, modified version of
source1.cpp
(orsource2.cpp
, for what it matters):The compiler will certainly complain here about
f()
being redefined. That's obvious: its definition is being included twice! However, the abovesource1.cpp
will compile without problems whenheader.h
contains the proper include guards. That's expected.Still, even when the include guards are present and the compiler will stop bothering you with error message, the linker will insist on the fact that multiple definitions being found when merging the object code obtained from the compilation of
source1.cpp
andsource2.cpp
, and will refuse to generate your executable.Basically, each
.cpp
file (the technical term in this context is translation unit) in your project is compiled separately and independently. When parsing a.cpp
file, the preprocessor will process all the#include
directives and expand all macro invocations it encounters, and the output of this pure text processing will be given in input to the compiler for translating it into object code. Once the compiler is done with producing the object code for one translation unit, it will proceed with the next one, and all the macro definitions that have been encountered while processing the previous translation unit will be forgotten.In fact, compiling a project with
n
translation units (.cpp
files) is like executing the same program (the compiler)n
times, each time with a different input: different executions of the same program won't share the state of the previous program execution(s). Thus, each translation is performed independently and the preprocessor symbols encountered while compiling one translation unit will not be remembered when compiling other translation units (if you think about it for a moment, you will easily realize that this is actually a desirable behavior).Therefore, even though include guards help you preventing recursive mutual inclusions and redundant inclusions of the same header in one translation unit, they can't detect whether the same definition is included in different translation unit.
Yet, when merging the object code generated from the compilation of all the
.cpp
files of your project, the linker will see that the same symbol is defined more than once, and since this violates the One Definition Rule. Per Paragraph 3.2/3 of the C++11 Standard:Hence, the linker will emit an error and refuse to generate the executable of your program.
If you want to keep your function definition in a header file that is
#include
d by multiple translation units (notice, that no problem will arise if your header is#include
d just by one translation unit), you need to use theinline
keyword.Otherwise, you need to keep only the declaration of your function in
header.h
, putting its definition (body) into one separate.cpp
file only (this is the classical approach).The
inline
keyword represents a non-binding request to the compiler to inline the function's body directly at the call site, rather than setting up a stack frame for a regular function call. Although the compiler doesn't have to fulfill your request, theinline
keyword does succeed in telling the linker to tolerate multiple symbol definitions. According to Paragraph 3.2/5 of the C++11 Standard:The above Paragraph basically lists all the definitions which are commonly put in header files, because they can be safely included in multiple translation units. All other definitions with external linkage, instead, belong in source files.
Using the
static
keyword instead of theinline
keyword also results in suppressing linker errors by giving your function internal linkage, thus making each translation unit hold a private copy of that function (and of its local static variables). However, this eventually results in a larger executable, and the use ofinline
should be preferred in general.An alternative way of achieving the same result as with the
static
keyword is to put functionf()
in an unnamed namespace. Per Paragraph 3.5/4 of the C++11 Standard:For the same reason mentioned above, the
inline
keyword should be preferred.First of all you should be 100% sure that you have no duplicates in "include guards".
With this command
you will 1) highlight all include guards, get unique row with counter per include name, sort the results, print only counter and include name and remove the ones that are really unique.
HINT: this is equivalent to get the list of duplicated include names