37

I'm cleaning up the includes in a C++ project I'm working on, and I keep wondering whether or not I should explicitly include all headers used directly in a particular file, or whether I should only include the bare minimum.

Here's an example, Entity.hpp:

#include "RenderObject.hpp"
#include "Texture.hpp"

struct Entity {
    Texture texture;
    RenderObject render();
}

(Let's assume that a forward declaration for RenderObject is not an option.)

Now, I know that RenderObject.hpp includes Texture.hpp - I know that because each RenderObject has a Texture member. Still, I explicitly include Texture.hpp in Entity.hpp, because I'm not sure if it's a good idea to rely on it being included in RenderObject.hpp.

So: Is it good practice or not?

  • 19
    Where are the include guards in your example? You just forgot them accidentally, I hope? – Doc Brown Nov 7 '14 at 6:36
  • 3
    One issue that occurs when you don't include all the used files is that sometimes the order you include the files then becomes important. That is really annoying in just the single case where it happens but that sometimes snowballs and you end up really wishing the person who wrote the code like that would be marched in front of a firing squad. – Dunk Nov 7 '14 at 14:23
  • This is why there are #ifndef _RENDER_H #define _RENDER_H ... #endif. – sampathsris Nov 8 '14 at 0:55
  • @Dunk I think you misunderstood the problem. With either of his suggestions that shouldn't happen. – Mooing Duck Nov 8 '14 at 16:25
  • 1
    @DocBrown, #pragma once settles it, no? – Pacerier May 14 '15 at 16:49
65

You should always include all headers defining any objects used in a .cpp file in that file regardless of what you know about what's in those files. You should have include guards in all header files to make sure that including headers multiple times does not matter.

The reasons:

  • This makes it clear to developers who read the source exactly what the source file in question requires. Here, someone looking at the first few lines in the file can see that you are dealing with Texture objects in this file.
  • This avoids issues where refactored headers cause compilation issues when they no longer require particular headers themselves. For instance, suppose you realize that RenderObject.hpp doesn't actually need Texture.hpp itself.

A corollary is that you should never include a header in another header unless it is explicitly needed in that file.

  • 10
    Agree with the corollary - with the proviso it should ALWAYS include the other header if it DOES need it! – Andrew Nov 7 '14 at 9:03
  • 1
    I dislike the practice of directly including headers for all individual classes. I'm in favour of cumulative headers. That is, I think the high level file should reference a "module" of some kind it is using, but need not directly include all of the individual parts. – edA-qa mort-ora-y Nov 7 '14 at 17:18
  • 8
    That leads to large, monolithic headers that every file includes, even when they only need little bits of what is in it, which leads to long compilation times and makes refactoring more difficult. – Steven Burnap Nov 7 '14 at 17:35
  • 6
    Google has built a tool to help it enforce precisely this advice, called include-what-you-use. – Matthew G. Nov 7 '14 at 18:44
  • 3
    The primary compile time issue with large monolithic headers is not the time to compile the header code itself but having to compiler every cpp file in your application every time that header changes. Precompiled headers don't help that. – Steven Burnap Nov 7 '14 at 23:32
23

The general rule of thumb is: include what you use. If you use an object directly, then include its header file directly. If you use an object A that uses B but do not use B yourself, only include A.h.

Also while we are on the topic, you should only include other header files in your header file if you actually need it in the header. If you only need it in the .cpp, then only include it there: this is the difference between a public and private dependency, and will prevent users of your class from dragging in headers they don't really need.

10

I keep wondering whether or not I should explicitly include all headers used directly in a particular file

Yes.

You never know when those other headers might change. It makes all the sense in the world to include, in each translation unit, the headers you know that translation unit needs.

We have header guards to ensure that double-inclusion is not harmful.

3

Opinions differ on this, but I am of the view that every file (whether c/cpp source file, or h/hpp header file) should be able to be compiled or analysed on its own.

As such, all files should #include any and all header files that they need - you should not assume that one header file has already been included previously.

It is a real pain if you need to add a header file and find that it uses an item that is defined elsewhere, without directly including it... so you have to go find (and possibly end up with the wrong one!)

On the other side, it doesn't (as a general rule) matter if you #include a file you don't need...


As a point of personal style, I arrange #include files in alphabetical order, split into system and application - this helps reinforce the "self contained and fully coherent" message.

  • Note about order of includes: sometimes the order is important, for example when including X11 headers. This can be due to design (which might in that case be considered bad design), sometimes it is due to unfortunate incompatibility issues. – hyde Nov 8 '14 at 8:44
  • A note about including unnecessary headers, it does matter to compilation times, first of directly (especially if it is template-heavy C++), but especially when including headers of same or dependency project where the include file also changes, and will trigger recompilation of everything including it (if you have working dependencies, if you don't then you have to be doing clean build all the time...). – hyde Nov 8 '14 at 8:49
2

It depends on whether that transitive inclusion is by necessity (e.g. base class) or because of an implementation detail (private member).

To clarify, the transitive inclusion is necessary when removing it can only be done after first changing the interfaces declared in the intermediate header. Since that's already a breaking change, any .cpp file using it has to be checked anyway.

Example: A.h is included by B.h which is used by C.cpp. If B.h used A.h for some implementation detail, then C.cpp shouldn't assume that B.h will continue to do so. But if B.h uses A.h for a base class, then C.cpp may assume that B.h will continue to include the relevant headers for its base classes.

You see here the actual advantage of NOT duplicating header inclusions. Say that the base class used by B.h really didn't belong in A.h and is refactored into B.h itself. B.h is now a standalone header. If C.cpp redundantly included A.h, it now includes an unnecessary header.

2

There can be another case: You have A.h, B.h and your C.cpp, B.h includes A.h

so in C.cpp, you can write

#include "B.h"
#include "A.h" // < this can be optional as B.h already has all the stuff in A.h

So if you don't write #include "A.h" here, what can happen? in your C.cpp, both A and B (e.g. class) are used. Later you changed your C.cpp code, remove B related stuff, but leaving B.h included there.

If you include both A.h and B.h and now at this point, tools that detect unnecessary includes may help you to point that B.h include is no longer needed. If you only include B.h as above, then it is hard for tools/human to detect the unnecessary include after your code change.

1

I am taking a similar slightly different approach from proposed answers.

In headers, always include just a bare minimum, just what is needed to make the compilation pass. Use forward declaration wherever possible.

In the source files, it is not that important how much you include. My preferences are still to include minimum to make it pass.

For small projects, including headers here and there will not make a difference. But for medium to large projects, it can become a problem. Even if the latest hardware is used to compile, the difference can be noticeable. The reason is that the compiler still has to open the included header and parse it. So, to optimize the build, apply the above technique (include bare minimum, and use forward declare).

Although a bit outdated, Large Scale C++ Software Design (by John Lakos) explains all this in details.

  • 1
    Disagree with this strategy... if you include a header file in a source file, you then have to track down all of its dependencies. It is better to include directly, than try and document the list! – Andrew Nov 7 '14 at 11:53
  • @Andrew there are tools and scripts to check what, and how many times, is included. – BЈовић Nov 7 '14 at 12:10
  • 1
    I have noticed optimization on some of the latest compilers to deal with this. They recognize a typical guard statement, and process it. Then, when #including it again, they can optimize out the file load completely. However, your recommendation of forward declarations is very wise to reduce the number of includes. Once you begin using forward declarations, it becomes a balance of compiler run-time (improved by forward declarations) and user-friendliness (improved by convenient extra #includes), which is a balance each company sets differently. – Cort Ammon Nov 8 '14 at 5:16
  • 1
    @CortAmmon A typical header has include guards, but the compiler still has to open it, and that is slow operation – BЈовић Nov 10 '14 at 6:45
  • 4
    @BЈовић: Actually, they don't. All they have to do is recognize that the file has "typical" header guards and flag them so that it only opens it once. Gcc, for example, has documentation regarding when and where it applies this optimization: gcc.gnu.org/onlinedocs/cppinternals/Guard-Macros.html – Cort Ammon Nov 10 '14 at 6:59
-4

Good practice is to not worry about your header strategy as long as it compiles.

The header section of your code is just a block of lines that nobody should even look at until you get an easily resolved compile error. I understand the desire for 'correct' style, but neither way can really be described as correct. Including a header for every class is more likely to cause annoying order-based compile errors, but those compile errors also reflect problems that careful coding could fix (though arguably they're not worth the time to fix).

And yes, you will have those order-based problems once you start getting into friend land.

You can think of the problem in two cases.


Case 1: You have a small number of classes interacting with each other, say less than a dozen. You regularly add to, remove from, and otherwise modify these headers, in ways that may affect their dependencies on each other. This is the case which your code example suggests.

The set of headers is small enough that it is not complicated to solve any problems that crop up. Any difficult problems are fixed by rewriting one or two headers. Worrying about your header strategy is solving problems which do not exist.


Case 2: You have dozens of classes. Some of the classes represent the backbone of your program, and rewriting their headers would force you to rewrite/recompile a great amount of your code base. Other classes use this backbone to accomplish things. This represents a typical business setting. Headers are spread across directories and you can't realistically remember the names of everything.

Solution: At this point, you need to think of your classes in logical groups and collect those groups into headers which stop you from having to #include over and over. Not only does this make life simpler, it is also a necessary step to taking advantage of precompiled headers.

You end up #includeing classes you don't need but who cares?

In this case, your code would look like...

#include <Graphics.hpp>

struct Entity {
    Texture texture;
    RenderObject render();
}
  • 13
    I had to -1 this because I honestly believe any sentence which is in the form of "Good practice is not to worry about your ____ strategy as long as it compiles" leads people to bad judgement. I have found that approach leads very rapidly towards unreadability, and unreadability is ALMOST as bad as "doesn't work." I have also found many major libraries which disagree with the results from both cases you describe. As an example, Boost DOES do the "collections" headers you recommend in case 2, but they also make a big deal out of providing class-by-class headers for when you need them. – Cort Ammon Nov 8 '14 at 5:23
  • 3
    I have personally witnessed "don't worry if it compiles" turn into "our application takes 30 minutes to compile when you add a value to an enum, how the hell do we fix that!?" – Steven Burnap Nov 12 '14 at 16:46
  • I addressed the issue of compile time in my answer. In fact, my answer is one of only two (neither of which scored well) that does. But really, that's tangential to OP's question; this is a "Should I camel-case my variable names?" type question. I realize my answer is unpopular but there isn't always a best practice for everything, and this is one of those cases. – QuestionC Nov 12 '14 at 17:57
  • Agree with #2. As to the earlier ideas - I hope for automation that would update the local header block - until then I advocate a complete list. – chux Jan 3 '15 at 7:27
  • The "include everything and the kitchen sink" approach may save you some time initially - your header files may even look smaller (since most of the things are included indirectly from.... somewhere). Until you come to the point where any change anywhere causes a 30+ minute recomple of your project. And your IDE-smart autocomplete brings up hundreds of irrelevant suggestions. And you accidently mix up two too similarly named classes or static functions. And you add a new struct but then the build fails because you have a namespace collision with an totally unrelated class somewhere... – CharonX Mar 20 '18 at 9:55

protected by gnat Mar 20 '18 at 6:50

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.