C ++的有效用途还包括防守,包括防护?

时间:2011-02-01 21:36:34

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

This question是讨论C ++命名约定的几种方法之一。提出这个问题的人认为这个命名惯例是:

#ifndef FOO_H
#define FOO_H

// ...

#endif

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

其他人说,除非需要添加更多内容以更好地避免碰撞(例如PROJECTNAME_FOO_H_SDFFGH69876GF),否则名称FOO_H就可以了,因为从上下文中可以清楚地了解其目的是什么(即,它位于相同名称文件的开头,很明显它是一个包含守卫。)

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

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

5 个答案:

答案 0 :(得分:4)

我认为这个问题本身就存在缺陷。术语“包含守卫”是指#define并且在防范多重包含的特定用途中检查#defined,这就是说它是唯一的用途

现在更一般地说,定义和条件编译可以用于其他事情,比如编写与平台相关的代码,并且只会在某些情况下编译...

FOO_HFOO_H_INCLUDED是否更好,我会一直说后者是最具表现力的,然后我会回到vi并输入FOO_H in我的下一个foo.h标题。同样,正如我在另一个问题的评论中所提到的,你已经习惯了这种模式:

#ifndef XXXXXXXXX
#define XXXXXXXXX

#endif

作为文件中的前两行和最后一行,您最终会注意到。如果你重复使用相同的名字,那就等到它会回来......

答案 1 :(得分: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 

答案 2 :(得分:1)

在我看来,包括警卫应该包括警卫而已。如果你想要条件编译,我会定义其他东西。如果你在代码中徘徊#if defined(FOO_H),我认为人们会发现这很奇怪,因为_H通常表示包含守卫。

我能想到的一件事是检查文件是否已被包含(呃!),这样你就不必自己包含文件了。与前向声明或#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

答案 3 :(得分:1)

  

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

我只在这里看到一个非常狭隘的用法,以避免在你只需要一个前向声明时包含一个标题,但是如果先前已经包含了标题,你想跳过前向声明。

然而,这不是今天编译C ++的瓶颈,而且总是有前向声明或总是包含头部的混淆是不值得的。

即使你需要吨 - 我的意思是数百到数千行这些前向声明 - 所以它确实变得有价值,你最好使用专用的标题,类似于< iosfwd>,而不是而不是在多个地方保持这一点。

答案 4 :(得分:1)

对于重新调整用途:除非文件的全部内容都被ifndef / define / endif包围,否则FOO_H实际上并不是文件包括后卫,它只是守护部分一份文件。所以可能不应该在整个文件后面命名。递归包含相同的文件是可以出现这种情况的一种情况。

那就是说,我怀疑即使如此,它的定义应该是非常明显的(无论如何,更明显的是,你所做的任何狡猾的事情并不简单,包括防守)。在任何你看到模式ifndef FOO / define FOO的地方,或者甚至只是ifndef FOO /定义很多东西,一个简单的注释可以使FOO的意义明显,如果它还没有。

如果问题的任何部分是令牌FOO_H是否可能用于其他目的:我猜你是否有一个名为uppercase.h的文件使用UPPERCASE_H作为包括后卫,然后可以想象与某人的rot13.h冲突,包含#define UPPERCASE_A ('N')等等。愚蠢的例子,但如果你在头文件中定义字母的属性那么认为其中一些是不可笑的可能以_H结尾。

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

因此,无论上下文和重新调整的问题如何,我都不会将FOO_H用作包含守卫。