包括声明之外包括警卫

Posted

技术标签:

【中文标题】包括声明之外包括警卫【英文标题】:Include statements outside include guards 【发布时间】:2015-04-29 20:43:26 【问题描述】:

我最近开始在一个项目中遇到这个问题:

#include <string.h> // includes before include guards
#include "whatever.h"

#ifndef CLASSNAME_H // header guards
#define CLASSNAME_H
// The code
#endif

我的问题:考虑到所有(包含的)头文件都是以相同的样式编写的:这会导致问题(循环引用等)。并且:有什么(好的)理由这样做吗?

【问题讨论】:

1) 包括警卫很好。 2)我希望只在标题中看到它们,并且我希望它们包装 ENTIRE 标题。 3) 我会使用包含代码的守卫。而且我不喜欢在标题中包含代码。 4)您的标题可以(并且应该)#include 任何它需要的东西。您可以放心地假设其他标头都应该有自己的包含守卫。 好吧,把你的整个头球放在后卫里面也没什么坏处。但是您包含的其他标头应该已经使用过一次“守卫”#ifndef 或#pragma。您几乎总是可以依靠遵循此约定的系统标头。 在包含防护之前没有理由包含包含。但是,如果 '' 和 '"whatever.h"' 有适当的保护,则无需担心。 我发现了一个例子,其中外部包含包含一个定义,然后排除了头文件的其余部分。如果我将它移动到包含保护中,它不再看到定义,即使它们包含在上一行中。我不明白 【参考方案1】:

潜在地,在包含防护之外有#include 可能会导致循环引用等。如果其他文件得到适当的保护,就不会有问题。如果其他文件都这样写,可能会有问题。

不,据我所知,没有充分的理由使用包含保护之外的 #include 行编写代码。

包含保护应该围绕标题的全部内容;我想不出有什么例外(当标头保护首先是合适的——C 标头&lt;assert.h&gt; 是一个没有标头保护的好理由)。

【讨论】:

【参考方案2】:

只要您没有循环包含(whatever1.h 包括 whatever2.h 其中包括 whatever1.h),这应该不是问题,因为代码本身仍然受到保护,不会被多次包含。

然而,它几乎肯定会影响编译时间(多少取决于项目大小),原因有两个:

    现代编译器通常检测“经典”包含守卫,然后忽略该文件的任何进一步#includes(就像#pragma once)。您显示的结构阻止了这种优化。 每个编译单元变得更大,因为每个文件将被更频繁地包含 - 就在预处理器再次删除所有非活动块之前。

无论如何,我想不出这样的结构会有什么好处。也许这是一些奇怪的历史原因的结果,比如在标准 C++ 时代之前在您的代码库中使用了一些晦涩的分析工具。

【讨论】:

以上是关于包括声明之外包括警卫的主要内容,如果未能解决你的问题,请参考以下文章

犯错误:多个定义...尽管包括警卫

警卫声明不一致

swift 斯威夫特 - 警卫声明

包括问题和包括警卫

c_cpp 包括警卫

C包括警卫[重复]