SoFunction
Updated on 2025-03-05

Study on the inclusion order of C++ header files

one. The views in the Google C++ Programming Style Guide

The company is implementing coding specifications, and the leaders propose to basically use the Google C++ Programming Style Guide.

Among them, the order in which the "Google C++ Programming Style Guide" contains header files is as follows:
 
Names and Order of Includes
link ▽Use standard order for readability and to avoid hidden dependencies:C library, C++ library, other libraries' .h, your project's .h.
All of a project's header files should belisted as descendants of the project's source directory without use of UNIXdirectory shortcuts . (the current directory) or .. (the parent directory). Forexample, google-awesome-project/src/base/ should be included as
 
#include "base/"
In dir/ or dir/foo_test.cc, whosemain purpose is to implement or test the stuff in dir2/, order yourincludes as follows:
 
dir2/ (preferred location — seedetails below).
C system files.
C++ system files.
Other libraries' .h files.
Your project's .h files.
The preferred ordering reduces hiddendependencies. We want every header file to be compilable on its own. Theeasiest way to achieve this is to make sure that every one of them is the file #included in some .cc.
 
dir/ and dir2/ are often in thesame directory (. base/basictypes_test.cc and base/), but can bein different directories too.
 
Within each section it is nice to order theincludes alphabetically.
 
For example, the includes ingoogle-awesome-project/src/foo/internal/ might look like this:

<span style="font-size:16px;"> 
#include "foo/public/" // Preferred location. 
 
#include <sys/> 
 
#include <> 
 
  
 
#include <hash_map> 
 
#include <vector> 
 
  
 
#include "base/" 
 
#include"base/" 
 
#include "foo/public/" 
 
 </span> 

Here I will talk about my understanding of the above (if it is inappropriate, please correct me if you are not right):

1. To enhance readability and avoid implicit dependencies, the following order should be used:C standard library, C++ standard library, header files of other libraries, and header files of your own project. However, the first thing that is included here is the preferred header file, that is, for example, the file should be included first. The preferred header file is to reduce hidden dependencies while ensuring that the header file and implementation file are matched. A specific example is: If you have a cc file (the suffix of the Linux platform cpp file is cc) is Google-awesome-project/src/foo/internal/, then the order of the header files it contains is as follows:

<span style="font-size:16px;">#include "foo/public/" // Preferred location. 
 
#include <sys/> 
#include <> 
 
#include <hash_map> 
#include <vector> 
 
#include "base/" 
#include "base/" 
#include "foo/public/" 
 
</span> 

2. When including the header file, you should add the folder name of the project where the header file is located. That is, if you have such a project base and there is one inside, then the header file that contains the outside should be written like this:

#include "base/", not #include ""
 
What we see is that the hidden purpose behind the principles advocated by the Google C++ Programming Style Guide here is:

1. In order to reduce hidden dependencies, and at the same time, the header file matches its implementation file, its preferences (i.e. its corresponding header file) should be included first.
 
2. In addition to preferences, the principles from general to special are followed. However, I think the order of "Google C++ Programming Style Guide": the C standard library, C++ standard library, other library header files, and the header files of your own project are missing the first item: operating system-level header files. For example, the above example sys/ is probably not classified as C standard library, but the SDK provided by the Linux operating system. Therefore, I think the more accurate statement should be: OS SDK .h, C standard library, C++ standard library, header files of other libraries, and header files of your own project.
 
3. The reason why you want to list the project directory where the header file is located should be that the namespace is the same, which is to distinguish files that are renamed accidentally.
 
two. Different Perspectives in "C++ Programming Thoughts"
  
Unlike the Google C++ Programming Style Guide, C++ Programming Thought advocates a different rule. "C++ Programming Thoughts" P432 mentioned:

The order in which the header files are included is from "most special to most general". That is, any header files in the local directory are first included. Then there are all our own "tools" headers, followed by third-party library headers, followed by standard C++ library headers and C library headers.

To understand the reason: You can read a passage from John Lakos in "Large ScaleC++ Softwre Design" (Note: The translation is "Massive C++ Programming"):
 
Ensure that the components of the .h file are not parse by itself, which can avoid potential usage errors. Because it lacks a clear statement or definition that is resolved by itself. Including the .h file on the first line of the .c file ensures that all internal information blocks that are important to the physical interface of the component are in .h (if certain information blocks are indeed missing, you can find this problem once the .c file is compiled).
 
If the order in which the header files are included is "from most special to most general", if our header files are not parsed by itself. We will find it right away to prevent trouble from happening.
 
three. My experiment
 
Which one contains the best order? I used VS 2005 to compile a console test project TestInc, which has several files inside.
 
The code is as follows:

<span style="font-size:16px;">#pragma once 
 
#pragma once 
double acos(double Num); 
</span> 

The code is as follows:

<span style="font-size:16px;">double acos(double Num) 
{ 
  return 1.0; 
} 
 
</span> 

The code is as follows:

<span style="font-size:16px;">#include "" 
#include "" 
#include <> 
#include <> 
 
 
int _tmain(int argc, _TCHAR* argv[]) 
{ 
  double a = acos(0.5); 
  return 0; 
} 
</span> 

The result is an error:

1>c:\program files\microsoft visualstudio 8\vc\include\(107): error C2732: Early specification conflict between link specification and "acos"
1>        c:\program files\microsoft visual studio 8\vc\include\(107): See the statement of "acos"
 
Then I changed the order of inclusion of the header file to:

<span style="font-size:16px;">#include "" 
#include <> 
#include <> 
#include "" 
</span> 

Then the compile is passed. When debugging and running, main function calls are still a function acos in the C standard library. It seems that the order of function calls is in the order of inclusion of the header file, that is, my customized acos function is overwritten (if inline functions are included, inline functions are preferred).
 
From this small experiment, I came to the following conclusion: The order of header files advocated by "Google C++ Programming Style Guide" and "C++ Programming Thought" have their own advantages. "Google C++ Programming Style Guide" should greatly reduce hidden header file dependencies, while "C++ Programming Thought" can easily let you know clearly whether the interface you define conflicts with system libraries and third-party libraries.
 
Four. Precompiled functions in header files
 
In the development of Visual Studio environment, we found that almost every cpp file must contain this file and put it in the front position, otherwise an error will occur. Why is this?
      
It turns out that Visual Studio uses a precompiled mechanism. To understand the precompilation mechanism, let’s first introduce the precompilation header. The so-called precompiled header is to precompile the part of the code in a project and put it in a file (usually with the .pch as the extension). This file is called a precompiled header file. These precompiled codes can be any C/C++ code or even inline functions, but they must be stable and will not be changed frequently during the engineering development process. If these codes are modified, you need to recompile and generate precompiled header files. Note that generating precompiled header files is time-consuming. At the same time, you have to note that precompiled header files are usually large, usually 6-7M large. Pay attention to cleaning up useless precompiled header files in time.
 
Maybe you will ask: Today's compilers have the function of Time stamp. When the compiler compiles the entire project, it will only compile those modified files, and will not compile those files that have not been modified since the last time they have been compiled. So why precompile header files? Here is the answer, we know that the compiler is compiled in files. After a file is modified, the entire file will be recompiled. Of course, all the things in the header files (.eg Macro, Preprocessor) contained in this file must be processed again. This part of the information is saved by the precompiled header file of VC. To avoid having to reprocess these header files every time.
 
According to the above, the function of precompiled header files is of course to increase the cheap speed. With it, you don't need to compile code that does not need to be changed frequently every time. The compilation performance will certainly improve.
 
To use a precompiled header, we must specify a header file that contains code and other header files that we will not change frequently. Then we use this header file to generate a precompiled header file (.pch file). I believe everyone knows this file. Many people think this is a "system-level" file provided by VC, a header file provided by the compiler. Actually, it's not, this file can be of any name. Let's examine the precompiled header file of a typical MFC Dialog Based program generated by AppWizard. (Because AppWizard will specify how to use precompiled header files, by default, this is the name given by VC). We will find that this header file contains the following header file:

<span style="font-size:16px;">#include <> // MFC core and standard components 
#include <> // MFC extensions 
#include <> // MFC Automation classes 
#include <> // MFC support for Internet Explorer 4 Common Controls 
#include <> 
</span> 

These are the header files that must be included with MFC. Of course, we are unlikely to modify these header files in our project, so they are stable.
 
So how do we specify it to generate precompiled header files. We know that a header file cannot be compiled. So we also need a cpp file to generate the .pch file. The default is this file. There is only one code in this file: #include "". The reason is taken for granted. We just want it to be able to compile - that is, all we want is its .cpp extension. We can use the /Yc compilation switch to specify to generate a .pch file, and use the /Fp compilation switch to specify the name of the generated pch file. Open the project ->Setting->C/C++ dialog box. Point Category to Precompiled Header. Select the entire project in the tree view on the left. You can see /Fp "debug/" in Project Options (the white place in the lower right corner). This is the name of the generated .pch file. The default is usually <project name>.pch. Then, select in the tree view on the left, and the original Project Option becomes Source File Option (it was originally a project, but now it is a file, of course it has changed). Here we can see the /Yc switch. The function of /Yc is to specify this file to create a Pch file. The file name after /Yc is the header file containing the stable code. Only one file in a project can have the YC switch. VC compiles it into an Obj file and a PCH file based on this option.

In this way, we set up the precompiled header file. That is, we can use the precompiled header function.

The following are the precautions:
 
1) If /Yu is used, that is, precompilation is used. We will include the .h file you specified to generate the pch file (default is) at the beginning of each .cpp file, otherwise there will be problems. If you do not include this file, let me tell you the Unexpected file end.
 
2) If you accidentally lose the pch file, according to the above analysis, you just need to let the compiler generate a pch file. In other words, just recompile (that is, the cpp file specified by /Yc) once.

So is there such a precompilation mechanism under the Linux platform? If so, how is it implemented? The GCC compiler also implements a precompilation mechanism under the Linux platform. Here we take the project of open source IDE CodeBlocks (CodeBlocks has built-in GCC compiler) as an example to illustrate the implementation of the Linux platform:
 
Use CodeBlocks to build a C++ project, then create a new my_pch.h, and enter the following code:

&lt;span style="font-size:16px;"&gt;/*************************************************************** 
  * Name: my_pch.h
  * Purpose: Header to create Pre-Compiled Header (PCH)
  * Author: ()

  * Copyright: ()
  * License:
  *Usage: Project build options -->Other options -->Fill in the following two lines
  -Winvalid-pch
  -include my_pch.h
  ****************************************************************** 
 
#ifndef MY_PCH_H_INCLUDED 
#define MY_PCH_H_INCLUDED 
 
// put here all your rarely-changing header files 
 
#include &lt;iostream&gt; 
#include &lt;string&gt; 
 
#endif 
&lt;/span&gt; 

Then in the project build options -->Other options -->Fill in the following two lines

 -Winvalid-pch
 -include my_pch.h

You can enable precompiled file headers.
Then you can no longer use include header file, and you can compile it directly.

<span style="font-size:16px;">int main() 
{  
using namespace std; 
  cout << "Hello world!" << endl; 
  return 0; 
} 
</span> 

Even if you write the following line in the above code, it actually doesn't work:

<span style="font-size:16px;">#include <iostream> </span> 

The above is the entire content of the inclusion order of C++ header files brought to you by the editor. I hope everyone can support me~