【问题标题】:How to include the stdafx.h from the root directory?如何包含根目录中的 stdafx.h?
【发布时间】:2021-07-21 01:25:09
【问题描述】:

在 VS 中启用“显示所有文件”选项后,我添加了一个文件夹并在该文件夹中创建了一个新类。由于我使用的是预编译头文件,因此我还需要包含相对于新类文件的根目录中的 stdafx.h。

在我的 cpp 文件中,我有

#include "..\stdafx.h"

但我收到以下错误:

错误 C1010:查找预编译头文件时出现意外文件结尾。您是否忘记在源代码中添加“#include "stdafx.h""?

我的理解是,.. 应该指示编译器上一级目录?

【问题讨论】:

    标签: c++ visual-c++


    【解决方案1】:

    我建议使用:

    $(ProjectDir)/pch/my_pch.h
    

    as “预编译的头文件”
    和“高级>强制包含文件”

    这将在您的.cpp 文件的开头自动包含pch,因此无需在.cpp 文件中进行任何更改。

    而且这比更改包含目录要好,因为有时您可能在包含目录中有多个pch 文件,然后您无法确定使用了哪个文件。

    【讨论】:

      【解决方案2】:

      我通常也喜欢在我的项目中使用分层顺序,我发现有两种简单的方法可以包含预编译的标头:

      要么

      1. 把stdafx.h所在的目录放到编译器的include目录下。

        (属性 - VC++ 目录 - 包含目录:添加$(ProjectDir))

      或者

      1. 如果子目录不是太多,一个简单的绕过错误信息的方法是这样的:

        • 将stdafx.h 文件放入每个仅包含顶级stdafx.h 的子目录中:
          #include "..\stdafx.h"
        • 将#include "stdafx.h"写为子目录中所有源文件的第一行,而不是在其中包含顶级文件。

      这样,您所有的代码文件都使用相同的预编译头文件,无需进行其他复杂的设置。

      【讨论】:

      • 使用 MSVC 编译器,选项 #1 和 #2 有效。使用 Intel Compiler v19.0,选项 #2 有效(但不是 #1)。
      【解决方案3】:

      有趣的是,我使用的技巧不在答案中:

      1. 在项目的根文件夹中创建stdafx.h和stdafx.cpp。
      2. 转到项目属性 -> 预编译头文件。改为“使用”。
      3. 转到 stdafx.cpp,右键单击属性 -> 预编译头文件。改为“创建”。
      4. 转到项目属性 -> 高级;将“强制包含文件”更改为 stdafx.h;%(ForcedIncludeFiles)

      不要更改任何 CPP 文件;保持你的头文件原样。按原样构建。

      没有打字,没有 RSI,没有包含路径的麻烦,没有其他痛苦和痛苦。美妙之处在于,当您将解决方案移至另一个平台时,它仍然可以工作。太棒了。

      【讨论】:

        【解决方案4】:

        造成混淆的原因是 Visual Studio 将包含预编译头的 include 指令与其他 include 指令区别对待。具体来说,它不会使用正常的路径查找方法来查找预编译的标头,而是尝试通过简单的字符串比较将包含指令与项目配置中定义的指令进行匹配。

        预编译器头配置是全局设置的,但可以按文件覆盖。正常的全局配置(通过 Project Properties -> Configuration Properties -> C/C++ -> Precompiled Headers 访问)是:

        Precompiled Header: Use (/Yu)
        Precompiled Header File: stdafx.h
        Precompiled Header Output File: $(IntDir)$(TargetName).pch
        

        默认情况下,此配置应用于项目中的所有文件。但是,stdafx.cpp 的配置是在文件级别设置的,并将 Precompiled Header 值覆盖为:

        Precompiled Header: Create (/Yuc)
        

        这样做的效果是,对于配置为使用预编译头文件的任何源文件(默认情况下是除 stdafx.cpp 之外的所有源文件),VS 将查找与配置的预编译头文件值匹配的包含指令。例如

        #include "stdafx.h"
        

        因为检查使用简单的字符串比较而不是任何类型的目录搜索,所以(无论源文件相对于项目根目录的位置或 stdafx.h 文件的位置)使用的路径和文件名在 include 指令中必须与项目的预编译头文件配置设置使用的完全匹配。这样做的意外副作用是,如果您有一个包含各种源文件的项目子目录,则在这些文件中您不需要使用 ..\stdafx.h 之类的相对路径引用 stdafx.h 文件(如果您使用 VS将引发一个错误,指出它在查找预编译头时遇到了文件结尾)。

        只需使用朴素的#include "stdafx.h" 就可以正常工作,因为 VS 会将此识别为使用预编译头的指令,并且由于 stdafx.cpp 预编译,它已经知道正确的预编译头在哪里标头配置设置为“创建 (/Yc)”。

        【讨论】:

          【解决方案5】:

          如果您的项目的 .cpp 和 .h 文件位于不同的子目录中(不是明确地位于项目目录中),那么使用相对于解决方案目录的包含路径将是一种很好的编码风格(如果您不使用专用的包含目录)。特别是如果您在一个解决方案中有多个项目并且需要共享包含文件(例如,为了项目之间的互操作性,例如 .exe 和 .dll)。

          要重构您的项目,您需要执行以下操作:

          1. 在每个项目中指定额外的包含目录 $(SolutionDir) :右键单击项目,单击“属性”,转到 “配置属性”->“C/C++”->“常规”(为所有 一次配置,从 “配置”下拉菜单)
          2. 转到“C/C++”->“预编译头文件” 并将“预编译头文件”值更改为相对于的路径 解决方案目录,例如PROJECT_NAME/stdafx.h
          3. 在您的 .cpp 中 文件包括“PROJECT_NAME/stdafx.h”,而不仅仅是“stdafx.h”
          4. 在您的 .h 和 .cpp 文件中,当包含某些内容时,使用路径作为 “PROJECT_NAME/dir1/dir2/file.h”,除非包含来自 同一目录

          【讨论】:

          • 使用根目录包含路径是一个真的坏主意。将源代码复制到另一台机器,甚至重新配置源代码所在的机器都不会导致任何编译。此外,如果您使用根路径包含 stdafx.h,Visual Studio 仍然会抱怨,因为它不使用标准路径解析算法来定位 stdafx.h 文件,它有一些(imo 半角)自定义查找机制,实际上是问题的原因。
          • @Neutrino,我的意思不是完全根植于包含路径,例如以驱动器号开头的路径,例如C:。我已经编辑了答案以使含义更清楚:我的意思是解决方案目录或专用的 include 目录作为根目录,以便包含文件由相对于这些目录的路径引用。这使得在同一台计算机上的计算机或目录之间移动整个解决方案没有问题。
          • @Neutrino,另外,我已经仔细检查了使用解决方案相关路径(如#include "PROJECT_NAME\stdafx.h")的建议,如果遵循上述步骤,它就可以工作。如果您尝试过但没有成功,那是什么错误?
          • 在根路径上足够公平。但是,您不需要建议调整项目的 Additional Include Directories 配置以使 Visual Studio 能够找到源文件子目录的预编译头文件。详情见我的回答。
          【解决方案6】:

          您可以根据每个文件调整预编译头设置。

          1. 在解决方案资源管理器中右键单击 .cpp 文件,选择“属性”。
          2. 我强烈建议在配置下拉列表项中选择“所有配置”。
          3. 浏览到“C/C++”-“预编译头文件”。
          4. 将“预编译头文件”从“stdafx.h”调整为您需要的任何内容(例如"../stdafx.h")。

          请注意,这是单调乏味且容易出错的,因为它是在每个文件的基础上完成的,将来向您的项目添加文件的开发人员必须遵循相同的步骤。如果不这样做,他们将面临警告和错误,例如:

          • warning C4627: '#include "<path>"': skipped when looking for precompiled header use.

          和

          • fatal error C1010: unexpected end of file while looking for precompiled header. Did you forget to add '#include "stdafx.h"' to your source?

          这并没有给出关于这种或任何其他方法的太多指示。

          我猜他们最终会转向 StackOverflow 并最终来到这里……您好,感谢您的阅读。

          在此基础上,值得采用替代方案,例如将 $(ProjectDir) 放在 C++ 包含路径(在 C++\General 下),但在包含其他头文件时可能会导致混淆。

          【讨论】:

            【解决方案7】:

            Visual C++ 允许您定义几种设置预编译头文件的方法。最常见的是在项目配置级别为所有源文件启用它,在 Configuration Properties/C++/Precompiled Headers 下,设置“Precompiled Header”,选择“Use”。相同的位置,设置“预编译头文件”,通常是“stdafx.h”。所有文件都将获得此设置(因此项目中的配置)除了....

            一个文件负责生成 PCH 文件。该文件通常是项目中的 stdafx.cpp 文件,除了#include "stdafx.h" 之外,它通常没有任何内容。为那个文件配置预编译头文件,从“使用”切换到“创建”。这确保了如果 PCH 的主要标头不同步,stdafx.cpp 总是首先编译以重新生成 PCH 数据文件。在 Visual Studio 中还有其他配置 PCH 设置的方法,但这是最常见的。

            话虽如此,您的问题绝对令人恼火。用于启动 PCH 系统并在上面的“使用...”和“创建...”设置中指定的文件名必须与#include 中的文本完全匹配。

            因此,您很有可能可以通过在项目包含目录中添加“..”并从#include 语句中删除“..”来解决您的问题。您也可以在项目配置级别将其更改为“..\stdafx.h”作为直通标题,但如果您在多个文件夹中分层放置源文件,这可能会出现问题。

            哦,如果您在阅读 PCH 配置设置时不清楚,如果您不想将 PCH 用于任何特定的源文件(有时也有理由不这样做),您可以将其关闭以用于特定的源文件,否则请确保在每个源文件(c/cpp 等)的开头始终包含 #include "your-pch-include-file.h"。

            希望你能休息一下。

            【讨论】:

            • 嘿,谢谢你的回答,但我想我可能误解了你。配置属性中没有可用的“使用预编译头文件”设置。此外,我在配置属性 -> C\C++ -> 常规 -> 附加包含目录和配置属性 -> VC++ 目录 -> 包含目录中添加了“..”。它们都不起作用。
            • 我更新以反映 VS2010 配置路径设置。如果将“..”添加到包含路径,则还必须从 c/cpp 文件中“stdafx.h”的#include 声明中将其删除。
            • 我从 cpp 文件中删除了 stdafx.h 包含的“..\”部分,该文件位于单独的文件夹中。其他所有文件都可以正常编译,但单独文件夹中的文件现在会产生错误“错误 C1083:无法打开包含文件:'stdafx.h':没有这样的文件或目录”。
            • 如果您将所有预编译的头文件配置保留为默认值,那么在任何项目子目录的任何源文件中的简单#include "stdafx.h" 都应该可以正常编译。刚刚在 VS2012 上测试过。
            【解决方案8】:

            PCH 文件很奇怪,在 Visual Studio 中更是如此。编译使用 PCH 的 .cpp 文件时,VS 期望第一个非注释/空白文本为 #include "PCH_NAME_HERE"。 PCH_NAME_HERE 正是 PCH 的名称。没有目录,什么都没有。只是编译器选项中指定的 PCH 名称。

            如果你打算做这个目录伪造,那么你需要修改你的编译器设置,使 PCH 所在的目录在目录搜索路径中。这样,您就不需要 ..\ 部分。

            【讨论】:

              【解决方案9】:

              使用引号表示它是您自己的头文件使用&lt;&gt;表示它是系统头文件如果我没记错只需使用#include &lt;stdafx.h&gt;并让编译器找到它

              【讨论】:

              • -1: stdafx.h 不是系统文件。它是一个预编译的头文件。
              • 不是windows人,为什么它有一个.h扩展名?
              • 因为是头文件。它可能是预编译的,但它仍然是一个头文件。
              • 头文件是一个头文件——预编译——意味着它以某种方式被改变了。 .o 文件只是预编译的 .c 文件 :-) 为什么扩展名没有更改?并不是说扩展是文件格式的全部和结束
              • 实际的预编译文件不是.h文件。如,那不是它的名字。当编译器被告知存在 PCH 时,它会在看到 #include "PCH_NAME_HERE.h" 时替换预编译符号,方法是将 PCH_NAME_HERE.h 转换为带有预编译符号的文件的实际名称。 PCH_NAME_HERE.h 在技术上仍然是一个常规的头文件;这背后的想法是,您可以编译相同的文件,就好像它没有使用 PCH。
              猜你喜欢
              • 1970-01-01
              • 2015-03-14
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2012-07-10
              • 2016-08-18
              • 1970-01-01
              相关资源
              最近更新 更多