【问题标题】:Should we guard #include with #ifndef if the targeted file already has header guard?如果目标文件已经有标题保护,我们应该用#ifndef 保护#include 吗?
【发布时间】:2017-02-02 21:57:14
【问题描述】:

假设我们有两个类,Foo 和 Bar。

在 Foo.h 中

#ifndef MYPROJ_FOO
#define MYPROJ_FOO
....
# endif 

在Bar.cpp中,是否还需要保护include之类的

#ifndef MYPROJ_FOO
#include <Foo.h>
#endif

或者简单的#include 就足够了?如果我们已经有了 header 保护,那么包含保护对我来说似乎是多余的,但我经常看到这种做法,因此想知道我是否遗漏了一些东西。谢谢!

【问题讨论】:

  • 您不需要将它放在 .cpp 文件中,因为任何其他文件都不应该是 #included。
  • 不,你不需要这样做,因为你没有在其他文件中包含源文件。
  • 所有主要的编译器都会记住已经包含的文件的包含保护,所以这是多余的(并且容易出错)。

标签: c++ macros c-preprocessor include-guards


【解决方案1】:

从功能上讲,它没有任何区别。

旧代码可能使用它的一个原因是作为优化。这意味着预处理器可以避免第二次读取Foo.h,因此它可以更快地生成结果。

如今,即使预处理器确实第二次读取文件,其对性能的影响也应该足够小,不会被它打扰。一些预处理器甚至可以自动检测头保护,记住哪个头保护与哪个宏相关联,并避免自己重新读取头文件。

【讨论】:

    【解决方案2】:

    不,你不应该。包含守卫用于其他文件包含的标题。另一方面,源文件不应该包含在其他文件中。

    或者,您可以考虑在头文件中使用(非标准但普遍接受的)扩展名

    #pragma once
    

    【讨论】:

    • pragma 不可移植
    • @Raindrop7 true(如前所述),但由编译器广泛实现。还有我的个人喜好
    • 我看到的#pragma once 的一个问题是它是基于每个文件应用的。如果您的项目中有两个文件副本(多个不同模块共有),并且它们最终都包含(通过深度嵌套)到一个源文件中,则会发生冲突。
    • 同一文件的两个副本? --- 是时候重构了!
    • once 在挂载、符号链接和其他文件系统 ninjitsu 方面也存在问题。我的方法是谨慎使用,不要与您计划分享的任何内容一起使用。
    【解决方案3】:

    在Bar.cpp中,是否还需要保护include之类的

    #ifndef MYPROJ_FOO
    #include <Foo.h>
    #endif
    

    还是简单的#include就够了?

    从正确性的角度来看,简单的#include 就足够了。

    如果我们已经有了标头保护,那么包含保护对我来说似乎是多余的,但我经常看到这种做法,因此想知道我是否遗漏了什么。

    John Lakos 在他的书Large Scale C++ Software Design 中推荐了这种做法。

    不过,更好的选择是使用大多数现代 C++ 编译器都支持的 #pragma once 指令。

    Foo.h:

    #pragma once
    ....
    

    然后,你可以使用

    #include "Foo.h"
    

    在任何 .cpp 文件中。

    【讨论】:

      【解决方案4】:

      或者简单的#include 就足够了?

      是的。

      如果我们已经有标头保护,那么包含保护对我来说似乎是多余的,

      是的,这完全是多余的。

      但我经常看到这种做法

      我没有看到这种做法,除非代码作者不知道他们在做什么。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-04-23
        • 2020-10-15
        • 2010-12-20
        • 2011-10-03
        • 2017-11-29
        • 1970-01-01
        • 1970-01-01
        • 2022-09-30
        相关资源
        最近更新 更多