0

这个问题是讨论 C++ 命名约定的几个问题之一,包括警卫。问这个问题的人认为这个命名约定:

#ifndef FOO_H
#define FOO_H

// ...

#endif

单独使用时有点不直观(这是什么FOO_H意思?),我倾向于同意。

其他人则说,除非需要添加更多内容以更好地避免碰撞(PROJECTNAME_FOO_H_SDFFGH69876GFFOO_H清楚它是一个包含守卫)。

如果拥有的唯一目的是FOO_H防止多重包含,我可以购买它,但是我希望FOO_H在文件的其他地方有条件吗?我认为条件编译将是一个很好的理由,在这种情况下,将其命名为类似的名称FOO_H_INCLUDED会更清楚。

是否有类似的直接用途,或者我应该避免重新利用包含警卫?

4

5 回答 5

4

我认为这个问题本身就有缺陷。术语 include guards 指的是#defines 和 check for#defined防止多重包含的特定用途中,这可以说是唯一的用途。

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

不管是FOO_H不是FOO_H_INCLUDED更好,我总是说后者是最有表现力的,然后我会回到vi并输入FOO_H我的下一个foo.h标题。同样,正如我在对另一个问题的评论中提到的那样,您已经习惯了这种模式:

#ifndef XXXXXXXXX
#define XXXXXXXXX

#endif

作为文件中的前两行和最后一行,您最终会注意到。直到如果您重复使用相同的名称,它就会反击......

于 2011-02-01T21:52:32.383 回答
1

有时,我将它用于“实现”头文件。守卫的实际命名方案可能不同。

#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 
于 2011-02-01T21:50:55.760 回答
1

在我看来,包括警卫应该是包括警卫,仅此而已。如果你想要条件编译,我会定义别的东西。如果您在代码中乱扔垃圾#if defined(FOO_H),我认为人们会觉得这很奇怪,因为_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
于 2011-02-01T21:54:01.997 回答
1

我认为条件编译将是一个很好的理由,在这种情况下,将其命名为 FOO_H_INCLUDED 会更清楚。

当您只需要前向声明时,我在这里只看到一个非常狭窄的用途来避免包含标题,但如果之前已包含标题,则希望跳过前向声明。

但是,这不是当今编译 C++ 的瓶颈,并且对于始终具有前向声明或始终包含标头的额外混淆是不值得的。

即使你需要大量的——我的意思是成百上千行这些前向声明——这样它确实变得有价值,你最好使用一个类似于 <iosfwd> 的专用标题,而不是在多个地方维护它.

于 2011-02-01T22:03:00.623 回答
1

重新利用:除非文件的全部内容都被 ifndef/define/endif 包围,否则FOO_H它并不是真正的文件包含保护,它只是保护文件的一部分。所以可能它不应该以整个文件命名。递归包含同一文件是可能出现这种情况的一种情况。

也就是说,我怀疑即便如此,定义的用途应该很明显(无论如何,更明显的是,无论你在做什么棘手的事情都不简单,包括守卫)。在任何你看到模式 ifndef FOO/define FOO,或者甚至只是 ifndef FOO/define 很多东西的地方,一个简单的注释可以使 FOO 的含义变得明显,如果它还没有的话。

如果问题的任何部分是令牌是否FOO_H可能用于其他目的:我想如果您在某处有一个称为包含保护的文件uppercase.hUPPERCASE_H那么可以想象这可能与某人的rot13.h, #define UPPERCASE_A ('N')contains 等发生冲突。愚蠢的例子,但是,如果您在头文件中定义字母的属性,那么认为其中一些可能以_H.

更现实地说,我有一些项目包含在不同目录中具有相同基本名称的包含文件。

因此,无论上下文和重新利用的问题如何,我都不会FOO_H用作包含防护。

于 2011-02-02T02:26:39.097 回答