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.

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 #includes “math.h”. The preprocessor sees that MATH_H has previously been defined, and the contents between the header guards are skipped.

Thus, by adding the header guards, we’ve ensured that the contents of math.h are only included once in main.cpp.

For good form, we should also add header guards to geometry.h.

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.

Quiz

1) Using the math.h example above, add header guards to file geometry.h

Show Solution

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

138 comments to 1.10a — Header guards

  • urska

    So we have math.h

    geometry.h:

    and
    main.cpp:

    If I understand this correctly, the order in which we list #include "math.h" and #include "geometry.h" in main.cpp
    is important then?
    If #include "geometry.h" was listed first, then preprocessor sees that MATH_H has previously been defined when it comes to math.h (in this case listed second in main.cpp), and therefore, we lose function definition, that was included in it?

    • Alex

      No, order isn’t important. The important point is that main.cpp receives two copies of math.h (one directly, and one indirectly through geometry.h), and this happens regardless of which one was included first. The header guards save us from a duplicate definition problem.

  • GLASSIC

    I don’t really understand what are you trying to explain in "Header guards do not prevent a header from being included once into different code files" section. I guess there is a problem with .h and .cpp extensions in examples. or, are you assuming that code is compiled with "g++ main.cpp math.cpp -o main" or similar?

    • Alex

      Let’s say we have a header named a.h. Header guards will prevent a.h from being included into a single code file (say, a.cpp) more than once.

      However, now let’s say we have a second code file, b.cpp. Header guards will _not_ prevent a.h from being included once into a.cpp and once into b.cpp. That’s by design.

      It has nothing to do with the extensions or the compiler itself -- only to do with the fact that a.cpp and b.cpp are different files.

  • WÆTHERMAN

    Hi Alex! Great Website!

    *[…]If math.h included a function definition[…]*
    It **does** include a function definition in the example.

    I see in comments, that it has caused a lot of confusion that in previous lessons you advised to only put declarations in headers (to not put definitions there), and yet now you teach header guards, which help to deal with duplicate definitions. If I can make a suggestion, I think it would be nice to just mention that inconsistency in the article and comment that it still works as a double protection (if you break one rule, you are still protected by another practice) and it will also make more sense in future, and for further info on the issue (aside from going forward in the tutorial), one can read the comments, where some examples were already given. This way you wouldn’t break your convention of not mentioning concepts that weren’t yet explained earlier in the tut.

  • Jim

    I’m using Xcode and could not figure out why my Quiz code was working _before_ I even began to "fix" it! 8+|

    While I typed in the code given in the first part of the lesson, I failed to notice that Xcode was automatically adding the #ifndef…, #define… and #endif… lines in each new header file I created. Helpful, but probably not intended for learning the point of this lesson. Perhaps I should see if there is a setting in Xcode’s prefs for stopping this behavior for a while? LOL!

    Really enjoying your instruction method, even though I have to read some of the text several times! 😉
    A 74 tear old student!

  • Joey cummens

    I have a question regarding the subheader: Header guards do not prevent a header from being included once into different code files. Can you record it better? I do not understand this section. I understand what header guards are, but this section threw me off.

    Thank you.

    • Alex

      A header guard will prevent header.h from being included into c1.cpp twice.
      A header guard will not prevent header.h from being included into both c1.cpp and c2.cpp (one time each). This is by design.

  • Dan

    Hi Alex.

    I’m intrigued by the last example, more specifically the square.cpp file and the fact it doesn’t need to include the ‘square.h’ file.

    How does the square.cpp get the information from the square.h file when it hasn’t been included in this case?

    square.cpp:

    • Alex

      In this example, square.h contains the forward declarations for the functions in square.cpp and nothing else. Square.cpp doesn’t need these, so it doesn’t need to include square.h itself. Other files that want to use these functions do need to include square.h, so the compiler knows what the functions look like.

  • Marius

    Hello, Alex.

    The two

    statements in the second block of code are not indented 4 spaces/1 tab.

    Might just be to illustrate that it is possible. I do not know

  • hi Alex,
    one question please, i understand that duplicate definitions are the ones causing problems not duplicate declarations. is this the case for all duplicate declarations ? for examples:

    typedef struct foo{}; or struct foo{};
    => even tho we are defining a new types, they are considered declarations since they do not instantiates any memory for them right , so why they produce compiler errors

    while

    typedef int kraken;
    => wouldn’t cause any compiler error

    • Alex

      No, type definitions are immune from the duplicate definition rule, as long as the defined types are identical. I mention this in chapter 4 I think.

  • Srishti Jain

    I do not understand last example well. As main.cpp includes square.h it knows that the defination is in square.cpp But what if square.cpp is residing in a different project? So how would it link up the defination from one project to other?

    • Alex

      > As main.cpp includes square.h it knows that the defination is in square.cpp

      No, it actually doesn’t know this. Because square.h includes a forward declaration for the function, the compiler will assume the definition exists _somewhere_, but it doesn’t know where.

      > But what if square.cpp is residing in a different project? So how would it link up the defination from one project to other?

      If square.cpp is in a different project, then the compiler wouldn’t know about it or be able to access it from there. Generally, projects are independent from each other.

      • Srishti Jain

        I guessed the same logic but was not sure. Thankyou so much for replying. Your explanations and tutorials both are too good.
        Just one more thing. Will this complete tutorial help me master C++ concepts inside-out?

  • Victor

    Nice tutorials ! Considering a header file, I wonder if these constructors and destructors are functions definitions :

    I think they are but I often see that kind of statement in C++ projects. Does that mean that it will cause an error if that class is included into two files with no relations ?
    Thanks !

    • Alex

      No. Classes define a type, and both types and inline functions are excluded from the one definition rule.

      • Victor

        Thank you for your quick reply. If I understand correctly, the constructor and destructor will be converted to inline functions by the compiler and that’s why they can be included multiple times.

        • Alex

          Yup. The C++ spec says, “A member function may be defined (8.4) in its class definition, in which case it is an inline member function (7.1.2) …”

  • Jbucci77

    Dear Alex,

    Thanks for this free material, it’s simply awesome. I have one question, in previous lessons you mentioned definitions shouldn’t be done on headers files. However, I have seen them often in your exercises. Why?

    • Alex

      Often? I do put definitions in header files in this lesson to show you the downsides of doing so (the getSquareSides() example). Do I do so elsewhere?

  • McSteven

    Hi Alex,

    1) In "square.h" where the getSquareSides() function is defined, How is it defined multiple times in "main.cpp" since it is called once and from the beginning of one file which calls "square.h", SQUARE_H is defined until the end of this file and in another file it rebegin the process.

    2)What does SQUARE_H do since it is a macro?

    • Alex

      1) square.cpp and main.cpp both #include square.h. This copies getSquareSides() into each file, which is then compiled. The header guards don’t help here since each file (square.cpp and main.cpp) is compiled separately, and there’s no “memory” between files. Header guards only prevent the same header from being included more than once into the same file.

      2) It just defines a symbol in the preprocessor. We can then use #ifndef or #ifdef to see if that symbol has been defined or not.

  • Ken Z

    A c/cpp file should *always* include its associated header file (if it has one - main.cpp normally doesn’t …).
    Why?
    Well, to avoid the problem that occurs when the function signature is changed in the c/cpp file and you forget to change it also in the header file.
    If the header is included in the c/cpp file, then the compiler tells you right away about this error.

    IMHO, a pretty important rule

    • Alex

      This isn’t true. The compiler or linker will likely not complain about a mismatch between a forward declaration and the function definition, because it will assume the forward declaration is for some other similar function.

      You’ll only get an error if you try to call the function represented by the forward declaration (as it now doesn’t represent a function that has been defined). This is true regardless of whether the .cpp includes the .h or not.

  • Eduardo RM

    What’d be a best practice… Placing just forward declarations into a header file and then placing its definitions in a *.cpp source code file OR just in one step, putting the definitions into a header file???

    square.h

    square.cpp

    OR JUST…
    square.h

    • Alex

      Best practice is to put function forward declarations in the header, and the function definitions in the .cpp. You should generally not put function definitions in a header, as you risk ending up with duplicative definitions if the header is included into more than one file -- which will cause the linker to error.

  • Ben

    Hey Alex, thanks for the great lessons. One thing remains unclear to me…

    In the Quiz/Solution, we were asked to include guards to file geometry.h
    I would have thought that, since #include "math.h" is the one we’ve used twice and, as I understand it, need to guard against, that we would have included

    to the math.h file and left the geometry.h file as it is. As indeed you wrote in "Updating our previous example with header guards".

    Slightly confused
    Ben

    • Alex

      Not sure I follow your concern. Generally speaking you should always include header guards on your header files regardless of whether they’re used once or many times. There’s no downside to doing so.

      • Ben

        Cool, gotcha! I wasn’t sure what I was guarding against or if multiple guards create a problem, but then it obv doesn’t so all good, cheers.

  • Rohan

    Respected Sir,

    I have some doubt regarding the use of header guard. If multiple declaration does not raise any issue with compiler or linker then why we must prevent multiple inclusion of the header file as header file only consist of the declarations.
    For example the following code must work just fine .

    square.h:

    int getSquareSides();
    int getSquarePerimeter(int sideLength);

    square.cpp:

    int getSquareSides()
    {
        return 4;
    }

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

    main.cpp:

    #include <iostream>
    #include "square.h"

    int main()
    {
        std::cout << "a square has " << getSquareSides() << "sides" << std::endl;
        std::cout << "a square of length 5 has perimeter length " << getSquarePerimeter(5) << std::endl;

        return 0;
    }

    Please help me out as soon as possible.
    Thank you in advance.

    • Alex

      The answer is that there are many legitimate cases where it’s useful to put definitions in our header files.

      A good example is when we define our own types. We probably want to use those types in multiple files, so into the header files they go so they can be propagated out to wherever we need them. However, if one of these header files gets double-included, the compiler will complain. So the header guard helps prevent this. It’s easier and safer to always include a header guard (even when it’s not strictly necessary) than spend the time worrying about whether anything in your header can’t be double-included.

    • Rohan

      Thank you! for the clarification.

  • Lakshmanan Kanthi

    Suppose we have iostream included in 2 files main.cpp and trial.cpp on the same project. Then after creating object files, when linker comes into play and brings in the Standard library, we’ll be having multiple definitions for objects like cout right? Why doesn’t it raise an error?

    • Alex

      Good question. The answer is due to the difference between declarations and definitions.

      When you include iostream, you’re including the _declaration_ for std::cout not the definition. This allows the compiler to understand what std::cout is, and do all of the type checking it needs to make sure you’re using it correctly. Duplicate declarations are allowed, so there’s no problem with the declaration being propagated to multiple files.

      The definition of std::cout is precompiled into the C++ standard library, which is later linked into your program. This definition provides the actual functionality of std::cout, and since this is the only place std::cout is defined, there’s no duplicate definition problem.

      • Lakshmanan Kanthi

        Thank you sir! Till this date you’ve been helping people even though the website has been running way back since 2007. Many thanks!

  • “Note that duplicate declarations don’t cause the same kinds of problems since a declaration can be declared multiple times without incident. ”
    Hi, could you elaborate or give an example of how this works?
    If you have two or more similar declarations, wouldn’t it give you a linker error?
    Like so:

    Thanks for all your hard work!

    • Sorry, I figured it out - I mixed up definition and declaration.

    • Alex

      For anyone else having trouble here -- your example would give you a compiler or linker error, since your function definitions are definitions, not declarations. Here’s an update to your example showing a trivial/non-useful example of how you can have duplicate declarations.

  • Akshay

    How the code is running even we didn’t forward declare getSquareSides and getSquarePerimeter?

    • Alex

      The forward declarations are in square.h, which is #included into main.cpp. The #include causes the preprocessor to copy the contents of square.h into main.cpp at the point of inclusion.

  • Kevin

    Hello teacher Alex,
    Why header file have this "#pragma once" at first?

  • Jeremiah

    In this lesson, I noticed that no arguments are being passed to the function…

    Is this just an example or are there times where I should use a function in place of a variable?

    • Alex

      This function is an simplified example, to show off a particular language mechanic. It’s fairly unlikely you’d do this in practice. You’d most likely use a constant instead (which we discuss in the next chapter).

  • Advokat HadziTonic

    You don’t need to #include "square.h" in the square.cpp file. If all your function call’s are from main() then you need to #include "square.h" just in main(). All of your function definitions should live in main.cpp or in square.cpp, and all of function declarations should live in square.h file.

    Great tutorials by the way!

  • Rohit

    Hi there!
    Its just a little confusion.
    I need to know when we write [#include "square.h"] in main.cpp, will it include the file named square.h or square.cpp?
    And please explain when we include square.h file how will the getside() will be defined twice in main.cpp?

    • Alex

      It will include square.h. If you want to include square.cpp, you need to add that to your project in your IDE.

      In the square.h example, getSquareSides() isn’t defined twice in main.cpp. In the math.h example it does -- once because main.cpp includes math.h directly, and once because main.cpp includes geometry.h which includes math.h.

  • Nurlan

    Hello, Alex
    below given programs the linker will complain about your program having multiple definitions for identifier getSquareSides!
    Even though whatever you explained a bit confusing for me.

    1)I could not able to get the meaning of of return statement here. As i know return statement should return (once is defined) to called function. As you gave example in further classes as break and return statements. You have mentioned clearly that return should returned in subfunction to main or where it is called. How this forward declaration is going to be defined in below program in square.h .
    you have stated above : The end result is that both square.cpp and main.cpp get a copy of the definition of getSquareSides().
    So, how they are you going to get or defined that forward declaration.My opinion is that the rule of conditional compilation  has to scan or go thought all statements in spite of return statement. Here, the rule of return statements are out.
    2) The second question is you have explained as if the preprocessor starts scaning from square.cpp not from main.cpp.The rule of c++ is that all programs should be started from main() function but here is a confusing. May be the preprocessor  has some certain rules to follow. Could you explain please if there is rule of it.
    Thanks in Advance.  
    square.h:
    #ifndef SQUARE_H
    #define SQUARE_H

    int getSquareSides()
    {
        return 4;
    }

    int getSquarePerimeter(int sideLength); // forward declaration for getSquarePerimeter

    #endif
    //===========================================================
    square.cpp:
    #include "square.h"  // square.h is included once here

    int getSquarePerimeter(int sideLength)
    {
        return sideLength * getSquareSides();
    }
    //=============================================================
    main.cpp:

    #include <iostream>
    #include "square.h" // square.h is also included once here

    int main()
    {
        std::cout << "a square has " << getSquareSides() << " sides" << std::endl;
        std::cout << "a square of length 5 has perimeter length " << getSquarePerimeter(5) << std::endl;

        return 0;
    }

    • Alex

      1) getSquareSides() isn’t a forward declaration -- it’s a full function definition. Any file that #includes square.h will get a full (duplicate) copy of the function. In the program you’ve quoted, square.cpp and main.cpp both receive a copy of the full function definition for getSquareSides(). This full function definition satisfies the compiler -- which means programs that call getSquareSides() should compile file -- but not the linker, due to the duplicate definitions.
      2) Preprocessing happens in the same order as files as compiled, which is determined by the IDE. It could be that square.cpp gets compiled first, or main.cpp gets compiled first. That said, how the program runs (starting from main()) is not impacted at all by this. Also, generally speaking, if you do things correctly, it shouldn’t matter what order your files get compiled or preprocessed.

  • My dear c++ Teacher,
    Please let me say something trivial. In last main.cpp file, #include <iostream> should be included for program run.
    With regards and friendship.

  • Matt

    Typo at the end of "Header guards". You wrote:
    "Even the standard library includes use header guards."

  • Foster

    Hi Alex, I have been enjoying these tutorials but the header guards I am running into a bit of a large troubleshooting problem.

    I have tried to recreate square.h square.cpp and main.cpp  and I am running into an issue starting from square.h which propagates through the rest of my code.

    square.h

    square.cpp

    main.cpp

    the biggest problem that is happening (which I am sure is a simple fix but I can not figure out) is VS is telling me that "IntelliSense:cannot open source file "square.h" ". In addition I made sure to bring in the square.h file into the header file folder of Main.cpp, and I brought Square.cpp into the source file folder of Main.cpp, so I do not know why it says it can not open source file.

    Thank you for all you help!!

    • Alex

      I’m not sure. Maybe the #include “stdafx.h” inside square.h is confusing it? Generally you should only #include “stdafx.h” from .cpp files, not from header files. Try removing that line and see if it helps.

  • RasmoLaxsus

    ok lets say a there is chem.h and bio.h files.

    chem.h contains:

    bio.h contains:

    both of these have header guards. If they are included into main like this;

    does this mean that chem.h will be ignored since it contained { int add (int x) } hence { int subtruct (int x) } will not be declared in main ?

    • Alex

      No. It means main.cpp will get two copies of the declaration for function add() (one from chem.h and one from bio.h). In this case, that won’t be a problem since these are just declarations, and C++ allows duplicate declarations. You only get into trouble when you have duplicate definitions (e.g. if add had a function body).

Leave a Comment

Put C++ code inside [code][/code] tags to use the syntax highlighter