Search

1.10a — Header guards

The duplicate definition problem

In lesson 1.7 -- Forward declarations and definitions, we noted that an identifier can only have one definition. Thus, a program that defines a variable identifier more than once will cause a compile error:

Similarly, programs that define a function more than once will also cause a compile error:

While these programs are easy to fix (remove the duplicate definition), with header files, it’s quite easy to end up in a situation where a definition in a header file gets included more than once. This can happen when a header file #includes another header file (which is common).

Consider the following example:

math.h:

geometry.h:

main.cpp:

This seemingly innocent looking program won’t compile! The root cause of the problem here is that math.h contains a definition. Here’s what’s actually happening. First, main.cpp #includes “math.h”, which copies the definition for function getSquareSides into main.cpp. Then main.cpp #includes “geometry.h”, which #includes “math.h” itself. This copies the definition for function getSquareSides into geometry.h, which then gets copied into main.cpp.

Thus, after resolving all of the #includes, main.cpp ends up looking like this:

Duplicate definitions and a compile error. Each file, individually, is fine. However, because main.cpp #includes two headers that #include the same definition, we’ve run into problems. If geometry.h needs getSquareSides(), and main.cpp needs both geometry.h and math.h, how would you resolve this issue?

Header guards

The good news is that this is actually easy to fix via a mechanism called a header guard (also called an include guard). Header guards are conditional compilation directives that take the following form:

When this header is included, the first thing it does is check whether SOME_UNIQUE_NAME_HERE has been previously defined. If this is the first time we’ve included the header, SOME_UNIQUE_NAME_HERE will not have been defined. Consequently, it #defines SOME_UNIQUE_NAME_HERE and includes the contents of the file. If we’ve included the header before, SOME_UNIQUE_NAME_HERE will already have been defined from the first time the contents of the header were included. Consequently, the entire header will be ignored.

All of your header files should have header guards on them. SOME_UNIQUE_NAME_HERE can be any name you want, but typically the name of the header file with a _H appended to it is used. For example, math.h would have the header guard:

math.h:

Even the standard library headers use header guards. If you were to take a look at the iostream header file from Visual Studio, you would see:

Updating our previous example with header guards

Let’s return to the math.h example, using the math.h with header guards. For good form, we’ll also add header guards to geometry.h.

math.h

geometry.h:

main.cpp:

Now, when main.cpp #includes “math.h”, the preprocessor will see that MATH_H hasn’t been defined yet. The contents of math.h are copied into main.cpp, and MATH_H is defined. main.cpp then #includes “geometry.h”, which just #includes “math.h”. At this point, the preprocessor sees that MATH_H has previously been defined, and the contents between the header guards are skipped.

Can’t we just avoid definitions in header files?

We’ve generally told you not to include definitions in your headers. So you may be wondering why you should include header guards if they protect you from something you shouldn’t do.

There are quite a few cases we’ll show you in the future where it’s desirable to put definitions in a header file -- for example, when it comes to user-defined types (such as structs and classes). We haven’t covered those topics yet, but we will. So even though it’s not strictly necessary to have header guards at this point, we’re establishing good habits now, so you don’t have to unlearn bad habits later.

Header guards do not prevent a header from being included once into different code files

Note that the goal of header guards is to prevent a code file from receiving more than one copy of a guarded header. By design, header guards do not prevent a given header file from being included (once) into different code files. This can cause unexpected problems. Consider:

square.h:

square.cpp:

main.cpp:

Note that even though square.h has header guards, the contents of square.h are included once in square.cpp and once in main.cpp.

Let’s examine why this happens in more detail. When square.h is included from square.cpp, SQUARE_H is defined until the end of square.cpp. This define prevents square.h from being included into square.cpp a second time (which is the point of header guards). However, once square.cpp is finished, SQUARE_H is no longer considered defined. This means that when the preprocessor runs on main.cpp, SQUARE_H is not initially defined in main.cpp.

The end result is that both square.cpp and main.cpp get a copy of the definition of getSquareSides(). This program will compile, but the linker will complain about your program having multiple definitions for identifier getSquareSides!

There are multiple ways to work around this problem. One way is to put the function definition in one of the .cpp files so that the header just contains a forward declaration:

square.h:

square.cpp:

main.cpp:

Now function getSquareSides() has just one definition (in square.cpp), so the linker is happy. Main.cpp is able to call this function (even though it lives in square.cpp) because it includes square.h, which has a forward declaration for the function (the linker will connect the call to getSquareSides() from main.cpp to the definition of getSquareSides() in square.cpp).

We’ll explore other ways to solve this problem in future lessons.

#pragma once

Many compilers support a simpler, alternate form of header guards using the #pragma directive:

#pragma once serves the same purpose as header guards, and has the added benefit of being shorter and less error-prone. The stdafx.h file that Visual Studio includes in projects that use precompiled headers makes use of this directive in place of header guards.

However, #pragma once is not an official part of the C++ language, and not all compilers support it (although most modern compilers do).

For compatibility purposes, we recommend sticking to header guards.

Summary

Header guards are designed to ensure that the contents of a given header file are not copied more than once into any single file, in order to prevent duplicate definitions.

Note that duplicate declarations don’t cause the same kinds of problems since a declaration can be declared multiple times without incident -- but even if your header file is composed of all declarations (no definitions) it’s still a best practice to include header guards.

Note that header guards do not prevent the contents of a header file from being copied (once) into different project files. This is a good thing, because we often need to reference the contents of a given header from different project files.

1.10b -- How to design your first programs
Index
1.10 -- A first look at the preprocessor

188 comments to 1.10a — Header guards

  • Udit

    This is one of the best c++ tutorials site I have seen.

  • Bjorn

    Hello the quiz question answer is in the text already and it has been explained before

  • timothy

    I'm having trouble understanding the point of the forward declaration in square.h, could someone help explain that to me? Thanks

  • Alex Buckley

    Alex, i don't normally comment on stuff online but this tutorial is awesome, of all the cpp tutorials I've searched up this one was by far the easiest to follow and didn't overwhelm me with 9 billion words per page. 10/10 would recommend.

  • DEXTER RAYNE

    Hi ALEX,

    CAN I SCREEN-RECORD CERTAIN PAGES FOR PERSONNEL USE ?

    THANKS FOR THIS AWESOME WEBSITE....

    • Alex

      Yes, you can do whatever you want with the content of the site for personal use only. It's redistribution or rebroadcasting that's harmful.

  • Sid

    Hi there Alex! I am not able to understand the difference between declarations and definitions..
    In the code:

    Shouldn't that be a declaration? Or am I wrong?

    • Alex

      * If you're actually allocating memory for something, it's a definition and a declaration.
      * If you're just telling the compiler about the existence of something (e.g. a new type, a forward declaration) that you're going to use later, it's a pure declaration.

      When you see int x used to create a local variable, that's acting as both a declaration and a definition. Because it's a definition, it's susceptible to the one definition rule. Thus, if you try to define int x; again in the same scope, you'll get an error.

  • amigo

    "Main.cpp is able to call this function (even though it lives in square.cpp) because it includes square.h, which has a forward declaration for the function (the linker will connect the call to getSquareSides() from main.cpp to the definition of getSquareSides() in square.cpp)."

    It doesn't work for me. I have gcc compliant c++11. square.cpp must be included also in main.cpp, otherwise the program do not find the definition of functions defined (not just declared) in square.cpp

    • nascardriver

      Hola amigo!

      Don't include source files. Tell your compiler to compile both files at the same time.
      For g++ the syntax is as follows, other compilers are similar

  • Elfry

    It's a bit late but HAPPY ANNIVERSARY! Your site is the best, sir!

  • hypost

    I think to know how c++ doesn't work really deepen my understanding more than learning how it works

  • Hello Alex,
    Don't you think we should now stick to #pragma once, just to make sure the code is readable, short and less error-prone?
    Most of the compilers these days have support for #pragma once.

    Regards,
    Ishtmeet.

    • Alex

      I generally try to recommend practices that are an official part of the C++ language, not compiler-specific extensions, even if they are widely adopted.

      I wish C++ would formally adopt #pragma once because it is better than explicitly specifying header guards. But until they do, I won't recommend it, because it may leave your program unable to be compiled on particular compilers.

      For what it's worth, the Google C++ style guide also recommends avoiding #pragma once.

  • Paulo Fernando

    Sorry if it's a noob question...
    I'm confused about this code:

    The preprocessor will look file by file and copy the contents of #includes inside each one that is doing a #includes right?
    So when geometry.h does a #include "math.h", it copies to it the: int getSquareSides() definition right?
    And when main.cpp does a #include "math.h" and #include "geometry.h", it is ALSO including int getSquareSides() definition right?
    Shouldn't the linker complain about this duplicate definition? Or the geometry.h won't copy the contents of math.h to itself?
    Help me find out what I'm missing here. Thanks.

    • nascardriver

      Hi Paulo!

      There's no duplicate definition, I've shown the include steps in this comment
      http://www.learncpp.com/cpp-tutorial/1-10a-header-guards/comment-page-3/#comment-322851

  • Some guy

    "Now, when main.cpp #includes “math.h”, the preprocessor will see that MATH_H hasn’t been defined yet. The contents of math.h are copied into main.cpp, and MATH_H is defined. main.cpp then #includes “geometry.h”, which just #includes “math.h”. At this point, the preprocessor sees that MATH_H has previously been defined, and the contents between the header guards are skipped."

    How can the preprocessor see that MATH_H has already been defined if there is no header guard for MATH.H in GEOMETRY.H?

    • nascardriver

      Hi!

      Let's look at what happens when the files have been included:

      Now, walk through the code line by line

      So the final code looks like this

      • Nguyen

        Hi nascardriver,

        Please allow me to make up a similar example.  What does the final code look like?  and What is the output?  Thank you.

        #ifndef MATH_H // MATH_H isn't yet defined,
        #define MATH_H // so we define it and go on.

           std::cout << "AAA" << std::endl;

        #endif // MATH_H

        #ifndef GEOMETRY_H // GEOMETRY_H isn't yet defined,
        #define GEOMETRY_H // so we define it and go on.

           std::cout << "BBB" << std::endl;

        #ifndef MATH_H // MATH_H is already defined
        #define MATH_H // This code won't be compiled

           std::cout << "AAA" << std::endl;

        #endif // MATH_H

        #endif // GEOMETRY_H

        int main()
        {
           std::cout << "CCC" << std::endl;
           return 0;
        }

        • nascardriver

          Doesn't compile so no output.
          You can check this yourself by generating pre-processed files. For g++ the command is

          -E  Stop after preprocessing
          -o  Output file

          Output for your code

  • Dear Teacher, please permit me a suggestion: In program

    change second return value to some number different than 5, to be clear that problem is same name of functions. Regards.

    • Alex

      It's actually better the way it is. If I changed it, people might assume the compiler only complains if the function definition is different. In fact, the actual definition content don't matter -- it's the fact that there's more than one definition (duplicate or not) that's the issue.

  • Dear Teacher, please let me following question.
    Header guards prevent duplicate header files. Is there way for prevent duplicate function declaration?

    • Alex

      No. Duplicate function declarations aren't a problem:

      However, Duplicate function definitions are a problem. You can generally avoid that by ensuring you define all your functions in .cpp files.

  • Ishak

    How come square.cpp doesnt require that you forward declare the function when it compiles or am I forgetting or confusing something?

    // It would be okay to #include square.h here if needed
    // This program doesn't need to.

    int getSquareSides() // actual definition for getSquareSides
    {
        return 4;
    }

    int getSquarePerimeter(int sideLength)
    {
        return sideLength * getSquareSides();
    }

    • Anuj

      bcoz square.cpp is a different .cpp file and it doesn't include main function which requires forward declaration to compile if functions are defined after main()...

      for example

  • Dear Teacher,
    Please let me ask you whether following source code is valid c++'s iostream header file. Symbols //@ and /// are confusing me. Former is before second "{" and before first "}".

    Regards.

  • gSymer

    What's the difference between .h and .cpp files? Can we write code inside .h files too (as in the third example)?

    • nascardriver

      Hi gSymer!

      You can write code inside header files, but that's not what they're meant for.
      Declarations go in header files and definitions in source files.

  • Dear Teacher, please let me say that word pragma is transliteration of greek word πραγμα. In general it means "thing" or "stuff". For more information see at
    http://www.wordreference.com/gren/%cf%80%cf%81%ce%b1%ce%b3%ce%bc%ce%b1
    Regards.

  • Dear Teacher, please let me say that in section "Header guards do not prevent a header from being included once into different code files", in second (correct) program (project) in main.cpp file, comment is

    I think correct is

    By the way, color is not the usual green but same as #include ... Regards.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]