头文件引用(#include)

头文件的类别大致可以分为以下几类:标准库STL、准标准库Boost、针对C++语言的第三方库(ACE等)、基于C++语言的第三方工具库(SQLite等)、同软件下,其他solution提供的接口、同solution下,其他project提供的接口、同project下,上一级目录提供的接口、同project下,当前目录提供的接口、同project下,子目录提供的接口。对于cpp文件,尚存在一种更为特殊的头文件,与本cpp文件构成接口与实现关系。如:同名的hpp与cpp;文件名虽然不同,但为多态场景,即具有继承关系。

头文件引用顺序

基本原则:

  • 由远及近
  • 由通用到特殊
  • 影响域逐渐缩小
  • 同类头文件按字母排序。

给定顺序如下:

  1. (cpp)接口与实现关系的接口文件
  2. 标准库STL
  3. 准标准库Boost
  4. 针对C++语言的第三方库(ACE等)
  5. 基于C++语言的第三方工具库(SQLite等)
  6. 同软件下,其他solution提供的接口文件
  7. 同solution下,其他project提供的接口文件
  8. 同project下,上一级目录提供的接口文件
  9. 同project下,子目录提供的接口文件
  10. 同project下,当前目录提供的接口文件

注:头文件的隐藏依赖 每一个头文件均应该自己自足,即在任意一个cpp文件中添加该hpp时,无需添加额外的头文件来保证编译通过,即隐藏依赖。如下所示: interface.hpp文件:

  #ifndef __INTERFACE_HPP__
  #define __INTERFACE_HPP__
  typedef std::vector<std::string> StringVector;
  #endif

cpp文件:

  #include <vector>
  #include <string>
  #include "interface.hpp"

这样可以编译通过?确实可以编译通过。 但,若我们在另外的cpp文件中需要包含interface.hpp,那么必须在interface.hpp引用之前对vector和string进行引用,否则将会编译不通过。即头文件的隐藏依赖。 所以,为避免隐藏依赖问题,在cpp中,将存在接口与实现关系的接口文件放在第一位置。

头文件引用方式

头文件引用方式有两种:#include <file.hpp>与#include “file.hpp”

  1. <> 该方式检索头文件,从系统路径与工程配置的引用路径中进行检索头文件。
  2. "" 该方式检索头文件,采用相对路径的方式,若未能找到,则采用<>的方式进行查找。

基本原则:

  • 绝对路径查找使用<>,相对路径查找使用""
  • 同project下,使用"“查找,隶属于其他库的头文件使用<>
  • 头文件引用中间无需使用空行分割不同的类别

头文件引用规范示例(cpp)

1
2
3
4
5
6
7
8
9
#include "CurrentItf.hpp"
#include <STL>
#include <Boost>
#include <ACE>
#include <SQLite>
#include <OverSolution.hpp>
#include <OverProject.hpp>
#include "../ParentItf.hpp"
#include "SubFolder/SonItf.hpp"

头文件引用规范示例(hpp)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include <STL>
#include <Boost>
#include <ACE>
#include <SQLite>
#include <OverSolution1.hpp>
#include <OverSolution2.hpp>
#include <OverSolution3.hpp>
#include <OverProject.hpp>
#include "../ParentItf.hpp"
#include "SubFolder/SonItf.hpp"
#include "SameFolderItf.hpp"

注1:单文件中头文件引用数量比较多,说明该文件承担了太多的能力,是时候拆分了。 注2:文中未对c头文件引用排序,原因是禁止c与c++方法交叉使用,涉及c接口调用的模块,先将c接口封装为c++接口。