c++ - 理解问题: Precompiled headers & include usage

标签 c++ include precompiled-headers

我遇到了有关预编译 header 和#include指令的用法的理解问题。
因此,我在这里得到了“stdafx.h”,并在其中包含了例如vector,iostream和string。显然,关联的“stdafx.cpp”仅包含“stdafx.h”。

因此,如果我设计自己的头文件使用例如vector或iostream中的“代码”,则必须包含头文件,因为编译器当时不知道声明。那么,为什么这里的一些帖子(include stdafx.h in header or source file?)说,即使其他文件包含所需的声明,例如在其他头文件中包含“stdafx.h”也不是一件好事。 vector ?因此,基本上没有关系直接包含 vector 或预编译的头文件都一样。

我当然知道,如果关联的源文件包含所需的头文件,则不必在另一个头文件中包含头文件,因为那时声明是已知的。好吧,这仅在头文件包含在某处的情况下才有效。

所以我的问题是:我应该避免在任何源文件中包含预编译的头文件,为什么?我有点困惑,因为我正在网上阅读矛盾的表达,我无论如何都不应该在头文件中包含任何内容,否则包含在头文件中?
那现在怎么了?

最佳答案

这将是一个有意图的笼统声明。 Visual Studio项目follows this general design中PCH的典型设置,值得回顾。说:

  • 设计您的头文件,就像没有PCH主头一样。
  • 切勿在 header 中构建包含顺序依赖关系,而您希望包含源文件先于 header 实现。
  • 尽管有PCH主 header (稍后我会介绍),但始终在源文件中的标准 header 之前包含自定义 header 。这使您的自定义 header 更有可能被正确定义,并且不依赖于包含源文件的先前包含的某些标准 header 文件。
  • 始终设置适当的包含防护或实用程序,以避免多个包含。它们对于正常工作至关重要。

  • PCH主 header 不包含在 header 文件中。设计标题时,这样做的目的是包括要编译的标题所需的所有内容(并且仅包含所需的内容)。如果包含源文件的实现需要其他包含内容,则可以在标题之后根据需要将其包含在内。

    以下是我如何设置在.h和.cpp文件中使用多个标准 header 的项目的示例。

    myobject.h
    #ifndef MYAPP_MYOBJECT_H
    #define MYAPP_MYOBJECT_H
    
    // we're using std::map and std::string here, so..
    #include <map>
    #include <string>
    
    class MyObject
    {
        // some code
    
    private:
        std::map<std::string, unsigned int> mymap;
    };
    
    #endif
    

    请注意,无论是否使用PCH,上述 header 都应在包含的任何.cpp中进行编译。转到源文件...

    myobject.cpp
    // apart from myobject.h, we also need some other standard stuff...
    
    #include "myobject.h"
    #include <iostream>
    #include <fstream>
    #include <algorithm>
    #include <numeric>
    
    // code, etc...
    

    注意myobject.h不希望您包含它依赖的内容。它在 header 中不使用<iostream><algorithm>等;我们在这里使用它。

    这是没有PCH的典型设置。现在我们添加PCH主站

    添加PCH主标题

    那么,我们如何设置PCH主 header 为该事情提供涡轮增压功能呢?为了这个答案,我只处理标准的头文件和第三方库头文件,这些头文件不会随项目开发而发生变化。您将不再要编辑<map><iostream>(如果是,请检查一下头)。反正...
  • See this answer有关通常如何在Visual Studio中配置PCH的信息。它显示了一个文件(通常是stdafx.cpp)如何负责生成PCH,其余的源文件随后通过包含stdafx.h来使用said-PCH。
  • 决定PCH中的内容。通常,这就是配置PCH的方式。将非 volatile 物品放在那里,其余的留给常规物品包括。我们正在使用许多系统头,这些头将成为我们PCH主站的选择。
  • 确保参与PCH Turbo模式的每个源文件都首先包含PCH主 header ,如(1)中的链接答案所述。

  • 因此,首先是PCH主 header :

    stdafx.h
    #ifndef MYAPP_STDAFX_H
    #define MYAPP_STDAFX_H
    
    // MS has other stuff here. keep what is needed
    
    #include <algorithm>
    #include <numeric>
    #include <iostream>
    #include <fstream>
    #include <map>
    #include <string>
    
    #endif
    

    最后,配置为使用此文件的源文件然后执行此操作。所需的最小更改是:

    更新:myobject.cpp
    #include "stdafx.h" // <=== only addition
    #include "myobject.h"
    #include <iostream>
    #include <fstream>
    #include <algorithm>
    #include <numeric>
    
    // code, etc...
    

    注意我说的最少。实际上,当PCH主机将它们插入时,这些标准头都不再需要出现在.cpp中。换句话说,您可以执行以下操作:

    更新:myobject.cpp
    #include "stdafx.h"
    #include "myobject.h"
    
    // code, etc...
    

    是否选择取决于您自己。我喜欢保留它们。是的,它可以延长源文件的预处理器阶段,因为它拉入了头文件,进入了include-guards,并丢弃了所有内容,直到最终的#endif为止。如果您的平台支持#pragma once(而VS则支持),则将成为无人问津。

    但是请不要误会:所有这些中最重要的部分是头myobject.h完全没有更改,并且不包含或不了解PCH主头。它不必,也不应该构建,因此必须。

    关于c++ - 理解问题: Precompiled headers & include usage,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31905712/

    相关文章:

    c++ - C++原子compare_exchange_weak

    c++ - Lambda 函数模板转换失败

    android - 在 Windows 上插入 android usb 时中断

    php 包含根目录以外的目录中的文件

    php - 当使用 include() 包含相对路径时,PHP 检查哪些目录?

    c++ - 您能推荐一款适合新手的有趣的驱动程序应用程序吗?

    java - 包含带有未封闭标签的 jsp 页面的问题

    c++ - Eclipse CDT - 预编译 header

    c++ - 为什么我需要在 C++ 中的所有文件中包含预编译头文件?

    g++ - 为什么g++找不到-I include-path中的预编译头?