0

Let's say we have a header file A.h which depends on things declared in B.h and C.h. B.h also depends an C.h and therefore includes it. In this case we don't need to include C.h in A.h and it will compile just fine without it.

But I am wondering what the best course of action is in these cases. If B.h somehow changes and no longer depends on C.h, A.h will break.

On the other hand if I think this through to the end it seems unneccessary/impractical to reinclude every single dependency.

A common case I have are standard libraries. In almost all my header files I would have to include <stdint.h> and <stdbool.h>. I often skip this because they were already included in one of the dependencies but this always feels kind of arbitrary.

Karsten
  • 1,814
  • 2
  • 17
  • 32
  • With properly authored headers with include guards, it does not matter how many times a header gets included indirectly. Although, through forward declarations you can usually cut down on the dependencies most of the time. – Tanveer Badar Jun 18 '19 at 10:56
  • 2
    If the file depends on symbols from the header, it should directly include the header file, and not rely on the header file being indirectly included. **Include What You Use** : https://include-what-you-use.org/ – Eljay Jun 18 '19 at 11:07
  • 2
    Related: https://stackoverflow.com/questions/56596929/explicit-direct-include-vs-non-contractual-transitive-include/56597432#56597432 – eerorika Jun 18 '19 at 11:13

2 Answers2

5

If B.h somehow changes and no longer depends on C.h, A.h will break.

Exactly. Why take the chance?

On the other hand if I think this through to the end it seems unneccessary/impractical to reinclude every single dependency.

If it's impractical, your file has too many dependencies and is probably too large.

Refactor it into smaller modules.

A common case I have are standard libraries. In almost all my header files I would have to include <stdint.h> and <stdbool.h>. I often skip this because they were already included in one of the dependencies but this always feels kind of arbitrary.

I admit to sometimes skipping these when I know one of my headers — expressly defined to bring the types I need into scope — has done this. It's unlikely to be refactored because it has these headers for this reason, not for some other dependency that may disappear.

But, ultimately, there's nothing wrong with including <stdint.h> and <stdbool.h> where you need it. I'm surprised that you find you need them in "almost all [your] header files", to be honest.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
3

The common practice - and rule of thumb I suggest - is that all headers should be self-contained.

In other words, if something in A.h can only compile if B.h is #included, then A.h should #include "B.h". That avoids forcing other code, whenever it needs to use A.h to do

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

That is recursive. Every included file should be self-contained. It also applies to your headers including standard headers.

To deal with potential problems of a header being included multiple times include guards should be employed in headers as well.

Like any rule of thumb, there are some circumstances where it doesn't apply. But those are relatively uncommon in practice.

Peter
  • 35,646
  • 4
  • 32
  • 74