3

Ok, may be this question have answer already but I don't know what keyword to search (most of my searched results are about include guard in .h only, but not in .cpp)

Sometimes I saw in cpp each #include line have a extra include guard (sometimes even the included .h already have the own include guard) like this: SomeClass.cpp

#ifndef__A__
#include A.h
#endif
#ifndef__B__
#include B.h
#endif
#ifndef__C__
#include C.h
#endif

instead of

SomeClass.cpp

#include A.h
#include B.h
#include C.h

, what is the function of this include guard?

Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
ggrr
  • 7,737
  • 5
  • 31
  • 53
  • They are called external include guards, generally made popular by the Large Scale C++ Software Design book. http://stackoverflow.com/questions/110436/cleaning-up-legacy-code-header-spaghetti/110608#110608 – Retired Ninja May 22 '15 at 05:18

3 Answers3

2

The practice of using include guards in .cpp files was recommended by John Lakos in his book Large-Scale C++ Software Design. I don't know whether any one before him had recommended the practice.

Say you have

A.h:

#ifndef __A__
#define __A__

#include "B.h"
#include "C.h"

// ...
// ...
// ...

#endif

B.h:

#ifndef __B__
#define __B__

// ...
// ...
// ...

#endif

C.h:

#ifndef __C__
#define __C__

// ...
// ...
// ...

#endif

SomeClass.cpp:

#ifndef __A__
#include "A.h"
#endif

#ifndef __B__
#include "B.h"
#endif

#ifndef __C__
#include "C.h"
#endif

When SomeClass.cpp is compiled, the contents of A.h is included. As a by-product of including the contents of A.h, the contents of B.h and C.h are also included. Also, the pre-processor macros __A__, __B__ and __C__ are defined. When the line

#ifndef __B__

is processed, since __B__ is already defined, the next line is skipped.

If SomeClass.cpp had just:

#include "A.h"
#include "B.h"
#include "C.h"

the file B.h has to be opened and processed. The contents of the file will not be included again due to the include guards but the file has to be opened and closed.

By using the first strategy, you avoid the cost of of opening and closing B.h and C.h. For large scale C++ project, John Lakos asserts, the cost is too much. Hence, the recommendation of using include guards even in .cpp files.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • 2
    Note that some modern compilers (such as GCC) remember header guards, which makes this technique redundant. – MSalters May 22 '15 at 10:21
1

It means don't even check the content of header file if the file is already included (symbol_specific_to_header is defined).

In ancient time when opening a file and checking whether contents are already included in header itself was costly (Cost of opening, reading and closing the header was very high) this trick was used to reduce the compile time.

But on modern systems this trick is not required. Though this doesn't cause any harm except the code is repeated and adding cluttering, this would work. Althout adding hashguards in include files is recommended.

This is how the header file looks and are included.

New style:

/* A.h */
#pragma once
...

or

/* A.h */
#ifndef A_H
#define A_H
...
#endif

usage:

#include "A.h"

Or precompiled headers are used.

Old style

The ancient style as mentioned by you:

/* A.h */
#define A_H
...

usage:

#ifndef A_H
#include "A.h"
#endif
Mohit Jain
  • 30,259
  • 8
  • 73
  • 100
  • 1
    Yip it's the cost of opening the file. – sashang May 22 '15 at 05:21
  • but doesn't it seem unnecessary to have B.h and C.h at all? imho they should be removed – tejas May 22 '15 at 05:41
  • @tejashs Sorry I could not understand your concern. Can you please elaborate. `b.h` and `c.h` are independent files just like `a.h` and may bve completely orthogonal. – Mohit Jain May 22 '15 at 05:57
  • if we know that b.h and c.h are included in a.h we dont need to include them in the cpp file at all. only a.h should suffice – tejas May 22 '15 at 07:43
  • @tejashs How do you know that `b.h` and `c.h` are included in `a.h`? I might have missed. Is it written in question somewhere or is implied? I read the question again but no luck. – Mohit Jain May 22 '15 at 07:48
  • I thought it was implied – tejas May 22 '15 at 08:22
  • @tejashs No I don't see it is implied by any of the sentence or code example. – Mohit Jain May 22 '15 at 10:12
0

It's to protect against including the same header twice.

A.h might look something like this

#define __A__
#include B.h

Without the guards, B.h would be included twice, which could cause errors. So the #ifndef lines in the cpp is just protecting itself from headers including other headers.

Ryan Bemrose
  • 9,018
  • 1
  • 41
  • 54