C+的有效使用+;除此之外,还包括守卫? 是讨论C++包含守护程序的命名约定的几种方法之一。提出该问题的人认为该命名约定: #ifndef FOO_H #define FOO_H // ... #endif

C+的有效使用+;除此之外,还包括守卫? 是讨论C++包含守护程序的命名约定的几种方法之一。提出该问题的人认为该命名约定: #ifndef FOO_H #define FOO_H // ... #endif,c++,c-preprocessor,include-guards,C++,C Preprocessor,Include Guards,这本身就有点不直观(什么是FOO_H的意思?) 其他人说,除非需要添加更多的内容以更好地避免碰撞(如PROJECTNAME\u FOO\u H\u SDFFGH69876GF),否则名称FOO\u H很好,因为从上下文中可以清楚地看出它的用途(即,它位于同名文件的开头,并且很清楚它是一个include-guard) 如果拥有FOO_H的唯一目的是防止多重包含,我可以买这个,但是在文件的其他地方有没有我想要的FOO_H?我认为条件编译是一个很好的理由,在这种情况下,将其命名为FOO_H_inclu

这本身就有点不直观(什么是
FOO_H
的意思?)

其他人说,除非需要添加更多的内容以更好地避免碰撞(如
PROJECTNAME\u FOO\u H\u SDFFGH69876GF
),否则名称
FOO\u H
很好,因为从上下文中可以清楚地看出它的用途(即,它位于同名文件的开头,并且很清楚它是一个include-guard)

如果拥有
FOO_H
的唯一目的是防止多重包含,我可以买这个,但是在文件的其他地方有没有我想要的
FOO_H
?我认为条件编译是一个很好的理由,在这种情况下,将其命名为
FOO_H_include
会更清晰

是否有与此类似的直截了当的用法,或者我应该避免重新调整include guards的用途?

有时,我将其用于“实现”头文件。防护装置的实际命名方案可能有所不同

#ifndef FOO_IMPL_H
#define FOO_IMPL_H

#ifndef FOO_H
#error Don't include this directly
#endif

// Ugly implementation of the stuff in foo.h, with an uncountable
// number of template and typename keywords

#endif 

我认为这个问题本身是有缺陷的。“包含防护”一词是指在防止多重包含的特定用途中,定义并检查定义的“包含防护”,也就是说,这是唯一的用途

现在更一般地说,定义和条件编译可以用于其他事情,比如编写依赖于平台的代码位,并且只能在某些情况下进行编译

无论是
FOO_H
还是
FOO_H_INCLUDED
更好,我总是说后者是最有表现力的,然后我会回到
vi
并在下一个
FOO.H
标题中键入
FOO_H
。同样,正如我在对另一个问题的评论中提到的,您逐渐习惯了这种模式:

#ifndef XXXXXXXXX
#define XXXXXXXXX

#endif

作为文件中的前两行和最后一行,您会注意到。如果你重复使用了同一个名字,它就会咬你……

在我看来,include-guard应该是include-guard,仅此而已。如果需要条件编译,我将定义其他内容。如果你在代码中到处乱扔
\If defined(FOO_H)
,我想人们会觉得这很奇怪,因为
\u H
通常表示包含防护

不过,我能想到的一件事是检查文件是否已经包含(duh!),这样您就不必自己包含文件了。与转发声明或
#pragma once

在main.cpp中:

#include "bar.h" // comment this line to see the difference
#include "foo.h"

int main()
{
    return 0;
}
在bar.h中:

#ifndef BAR_H
#define BAR_H

class BarClass
{
};

#endif
在foo.h中:

#ifndef FOO_H
#define FOO_H

#if !defined(BAR_H)
#error bar h was not included // forgot how to do compiler warnings...
#include "bar.h" // we should include the file
#else
#error bar h was included // same thing, should be changed to warning
#endif

// do something with BarClass

#endif FOO_H
我认为条件编译是一个很好的理由,在这种情况下,将其命名为FOO_H_include之类的名称会更清楚

我在这里只看到一个非常狭隘的用法,当您只需要一个转发声明时,可以避免包含一个头,但如果以前包含了头,则希望跳过转发声明

<>但是,这不是编译C++的瓶颈,而且总是有正向声明或总是包含头的混淆是不值得的。
即使你需要成吨——我的意思是成百上千行的远期申报——这样才有价值,你最好还是有一个专门的标题,类似于,而不是在多个位置维护它。

用于重新调整用途:除非文件的整个内容都被ifndef/define/endif包围,否则
FOO\u H
实际上不是一个包含保护的文件,它只是保护文件的一部分。所以它可能不应该以整个文件命名。相同文件的递归包含是可能出现这种情况的一种情况

也就是说,我怀疑即使如此,定义的目的应该是非常明显的(无论如何,更明显的是,无论你在做什么诡计,都不简单,包括保护)。无论您在何处看到ifndef FOO/define FOO模式,甚至只是ifndef FOO/define很多东西,一个简单的注释都可以让FOO的含义变得显而易见,如果它还没有出现的话

如果问题的任何一部分是标记
FOO_H
是否可能被用于其他用途:我想如果你有一个名为
uppercase.H
的文件,它使用
uppercase_H
作为包含保护,那么这可能会与某人的
rot13.H
发生冲突,其中包含
\define uppercase\u a('N')
,等等。这是一个愚蠢的例子,但如果您在头文件中定义字母的属性,那么认为其中一些字母可能以
\u H
结尾并不荒谬

更现实地说,我曾经有过包含文件的项目,这些文件在不同的目录中具有相同的基名称


因此,不管上下文和重新调整用途的问题如何,我都不会使用
FOO_H
作为包含保护。

我会让它单独存在。这感觉就像“如果它没有损坏,请继续修复它,直到它损坏为止”键入情况。这就是为什么我更喜欢
#pragma once
@James:
#pragma once
不允许您按照OP提到的条件编译。@James:有些人更喜欢标准保证有效的解决方案。@David:我想知道,是不是有什么类似于
#pragma once
的建议用于C++0x?这仍然不能阻止#include“foo.h”后跟#包括“foo_impl.h”。如果您真的想防止这种情况发生,有更好的方法,例如Boost如何始终如一地使用“detail”标记实现细节和约定(无需技术强制)用户应该忽略幕后的那个人。编译器可以缓存一些保护,以跳过实际读取文件的过程,而不必使用#pragma一次。