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一次。