组织包括

时间:2011-06-21 11:22:19

标签: c++ include

  • 是否有一些首选的方法来组织包含指令?
  • .cpp文件而不是.h文件中包含所需的文件会更好吗?翻译单位是否受到影响?
  • 如果我在.h文件和.cpp文件中都需要它,我应该将它包含在.h文件中吗?这有关系吗?
  • 将已定义的文件保存在预编译的头文件(stdafx.h)中,例如std和第三方库,这是一个好习惯吗?我自己的文件怎么样,我应该在创建它们的过程中将它们包含在stdafx.h文件中?

// myClass.h
#include <string>
// ^-------- should I include it here? --------

class myClass{
    myClass();
    ~myClass();

    int calculation()
};

// myClass.cpp
#include "myClass.h"
#include <string>
//  ^-------- or maybe here?  --------

[..]

int myClass::calculation(){
    std::string someString = "Hello World";
    return someString.length();
}


// stdafx.h
#include <string.h>
// ^--------- or perhaps here, and then include stdafx.h everywhere? -------

6 个答案:

答案 0 :(得分:25)

  1. 您应该将它们放在文件的顶部,所有这些都在一个地方。这是每个人都期望的。此外,将它们分组是有用的,例如,首先是所有标准标题,然后是第三方标题(按库分组),然后是您自己的标题。在整个项目中保持此顺序一致。它使得理解依赖关系变得更容易。正如@James Kanze指出的那样,将声明内容的标头放在首位也很有用。这样你就可以确保它首先包含它是有效的(这意味着它不依赖于它不包含它的任何包含)。
  2. 保持范围尽可能小,以便标题中的更改影响最少的翻译单元数。这意味着,只要可能,只在cpp - 文件中包含它。正如@Pedro d'Aquino所评论的那样,你可以尽可能使用前向声明来减少标题中包含的数量(基本上每当你只使用对给定类型的引用或指针时)。
  3. 两者 - 显式优于隐式。
  4. 经过一些阅读后,我相信如果你确信他们不再改变,你应该只在PCH中包含标题。这适用于所有标准标头以及(可能)第三方库。对于你自己的图书馆,你就是法官。

答案 1 :(得分:7)

Header file include patterns上的这篇文章对您有所帮助。

  
      
  • 是否有一些首选的方法来组织包含指令?
  •   

,您可以在上面的文章中找到它们。

  
      
  • 最好在.cpp文件中包含所需的文件而不是   .h文件?是翻译单位   受某种程度影响?
  •   

,最好将它们放在.cpp中。即使如果在定义另一种类型时需要定义类型,也可以使用前向声明。

  
      
  • 如果我在.h文件和.cpp文件中都需要它,我应该这样做   将它包含在.h文件中?会吗   事?
  •   

仅限于.h文件,但建议在头文件中转发声明,并包含在.cpp文件中。

  
      
  • 将已定义的文件保留在预编译中是一种好习惯   header(stdafx.h),例如std   和第三方图书馆?怎么样   我自己的文件,我应该包含它们   像我一样的stdafx.h文件   创造它们?
  •   

我个人没有使用过预编译的头文件,但早先在Stackoverflow上对它们进行了讨论:

Precompiled Headers? Do we really need them

答案 2 :(得分:5)

  

是否有一些首选方法来组织包含指令?

没有共同的约定。有些人建议对它们进行字母排序,我个人不喜欢它,并且更喜欢将它们保持逻辑分组。

  

最好在.cpp文件中包含所需的文件而不是.h文件吗?

总的来说,是的。它减少了编译器打开和读取头文件的次数,只是为了查看那里的包含保护。这可能会缩短整体编译时间。 有时,为了同样的原因,有人也建议在标题中向前声明尽可能多的类,并且实际上仅将它们包含在.cpp中。例如,“Qt人”这样做。

  

翻译单位是否会受到影响?

在语义上,没有。

  

如果我在.h文件和.cpp文件中都需要它,我应该将它包含在.h文件中吗?这有关系吗?

只需将其包含在标题中即可。

  

将已定义的文件保存在预编译的头文件(stdafx.h)中,例如std和第三方库,这是一个好习惯吗?我自己的文件怎么样,我应该在创建它们的过程中将它们包含在stdafx.h文件中吗?

预编译头可以显着减少编译时间。例如:我的一个项目包括boost::spirit::qi在20秒内编译PCH,80秒 - 没有。一般来说,如果你使用像boost这样的大量模板填充库,你会想要利用PCH的优势。

至于您的代码示例中的问题:,因为您不在标头中使用std :: string,最好将其包含在.cpp文件中。 #include <string> stdafx.h中的{{1}}也没关系 - 但这会给你的项目增加一些复杂性,你几乎不会注意到任何编译加速。

答案 3 :(得分:1)

(4)我不建议在stdafx.h中包含任何其他文件。或类似的“include_first.h”文件。直接包含到cpp或特定的h文件允许您显式表示代码的依赖关系并排除冗余依赖项。当您决定将单个代码分解为几个lib或dll时,它尤其有用。就个人而言,我只使用“include_first.h”(stdafx.h)等文件进行配置(此文件仅包含当前应用程序配置的宏定义)。
通过标记另一个文件来停止预编译而不是stdafx.h,可以为您自己的文件提供预编译的头文件(例如,您可以使用名为“stop_pch.h”的特殊空文件)。
请注意,对于预处理器的某些软件使用情况,预编译头文件可能无法正常工作(特别是对于BOOST_PP_ * 中使用的某些技术)

答案 4 :(得分:1)

从表现的角度来看:

更改stdafx.h中包含的任何头文件将触发新的预编译,因此它取决于代码的“冻结”程度。外部库是stdafx.h包含的典型候选者,但您当然也可以包含自己的库 - 这是基于您期望更改它们的频率的权衡。

此外,使用Microsoft编译器,您可以将它放在每个头文件的顶部:

#pragma once

这允许编译器在第一次出现后完全跳过该文件,从而节省了I / O操作。传统的ifndef / define / endif模式需要在每次包含时打开和解析文件,这当然需要一些时间。它肯定会积累并变得引人注目!

(确保将传统警卫留在那里,以便携带。)

答案 5 :(得分:0)

注意翻译单元中的类顺序必须正确或者某些c ++功能只是被禁用并导致编译时错误可能很重要。

编辑:添加示例:

class A { };
class B { A a; }; // order of classes need to be correct