Is it good practice to rely on headers being included transitively?

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:

#pragma once
#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?

6

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.

13

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.

1

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.

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.

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.

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.

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.

6

My rule: Every header should compile on its own, so if a.h needs b.h then it includes it. Every header has protection against multiple inclusion. And source files include only what they need.

In addition if you use #ifdef then the header file where the macro comes from MUST be included to avoid serious problems.

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();
}

6

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Is it good practice to rely on headers being included transitively?

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:

#pragma once
#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?

6

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.

13

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.

1

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.

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.

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.

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.

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.

6

My rule: Every header should compile on its own, so if a.h needs b.h then it includes it. Every header has protection against multiple inclusion. And source files include only what they need.

In addition if you use #ifdef then the header file where the macro comes from MUST be included to avoid serious problems.

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();
}

6

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật