#include标头保护格式?

时间:2008-11-24 18:30:38

标签: c++ header c-preprocessor

我知道这对项目没有什么影响,但是,假设您使用#defined标头保护C ++代码,您使用什么格式?例如假设一个名为foo.hpp的标题:

#ifndef __FOO_HPP__
...

#ifndef INCLUDED_FOO_HPP
...

#ifndef SOME_OTHER_FORMAT

我卖的是关于大写#defines的想法,但不能满足这些守卫的格式。

13 个答案:

答案 0 :(得分:20)

我总是在include guard中包含命名空间或相对路径,因为只有头名称被证明是危险的。

例如,您有一些大型项目,其中包含代码中的两个文件

/myproject/module1/misc.h
/myproject/module2/misc.h

因此,如果您为包含保护使用一致的命名方案,则可能最终在两个文件中都定义了_MISC_HPP__(非常有趣,无法找到此类错误)。

所以我和

结算了
MYPROJECT_MODULE1_MISC_H_
MYPROJECT_MODULE2_MISC_H_

这些名字相当长,但与双重定义的痛苦相比,这是值得的。

另一个选择,如果你不需要编译器/平台独立性,你可能会寻找一些#pragma once stuff。

答案 1 :(得分:14)

我总是使用INCLUDED_FOO_HPP

我不会使用双下划线,因为保留了双下划线。

答案 2 :(得分:13)

为了真正避免名称冲突,我使用GUID:

#ifndef GUARD_8D419A5B_4AC2_4C34_B16E_2E5199F262ED

答案 3 :(得分:10)

就个人而言,我只使用文件名FOO_HPP。 Google使用整个路径,如SRC_ENGINE_FAST_HPP。

  

某些名称和功能   签名总是保留给   实现:

     
      
  • 每个包含双下划线(_ _)或以。开头的名称   下划线后跟一个大写   信(2.11)保留给   任何用途的实施。
  •   
  • 以下划线开头的每个名称都保留给   实现用作名称   全局命名空间。
  •   

17.4.3.1.2/1

答案 4 :(得分:4)

我更喜欢这种格式:

#ifndef FOO_HPP
#define FOO_HPP

/* ... */

#endif // FOO_HPP
  • 一个简单的 #ifndef ,而不是 #if!defined(...),因为使用复杂条件进行标头保护很少有意义。
  • _HPP 部分将标识符标记为标题保护。
  • 没有前导下划线,因为此类标识符(以2个下划线或1个下划线和大写字母开头)保留用于实现。
  • 基本部分只是文件名 FOO 。但是,对于将要重用的库代码,建议在开头添加另一个部分。这通常是包含名称空间或“模块”名称,例如 MYLIB_FOO_HPP ,有助于避免命名冲突。

答案 5 :(得分:3)

如果您使用的是Visual Studio或Microsoft编译器,请使用pragma方式

#pragma once

答案 6 :(得分:2)

我用

 #if !defined(FOO_HPP_INCLUDED)

我更喜欢现代defined语法,因为它允许|| &安培;&安培;运营商,即使他们不在这里使用。

另外

 #ifndef __FOO_HPP__

在技术上是非法的,因为前导下划线是保留的。

答案 7 :(得分:1)

我总是使用

#ifndef FOOBAR_CPP

答案 8 :(得分:1)

我也总是使用以下内容:

#ifndef FOO_HPP
#define FOO_HPP 1

...

#endif

正如大多数人所提到的,不要在前面添加带有双下划线的符号,因为C ++标准保留这些符号以供实现内部使用。

您可能希望看看John Lakos的优秀书籍“大规模C ++软件设计”(Amazon link - 为脚本kiddy链接纳粹进行了清理),以了解有关标题包含的一些注意事项。

HTH

欢呼声,

罗布

答案 9 :(得分:1)

当我按时获得报酬,而且还没有公司标准时,我会使用:

#ifndef path_to_file_h
#define path_to_file_h

小写的原因是复制和粘贴文件名并用下划线替换斜杠更容易。 #ifndef的原因是它与#define很好地排列,使得更容易看到符号是相同的。不过,我喜欢GUID的想法,所以我可以尝试一下。

当我没有按时付钱,而不是将我的代码发布到野外时,我只使用#pragma once。与大多数其他可移植性问题不同,它现在就像现在一样容易添加包含警卫,并且可以由对代码库一无所知的人完成(例如我在一年的时间内,或者我发送代码的一些无辜的程序员) ,所以YAGNI适用。

答案 10 :(得分:0)

我倾向于使用:

#ifndef FILE_DATE_H_

(将_H_替换为适当的扩展名,如_HPP_等)。日期戳是为了避免与其他方向/库中的其他相同命名的标题发生冲突。

所以最后它看起来像这样:

#ifndef SOMEFILE_20082411_H_

答案 11 :(得分:0)

我用

<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>

<FILENAME_IN_ALL_CAPS>_INCLUDED_<YYYYMMDD>

保持与文件夹层次结构同步太烦人(重构的朋友),GUID太烦人,日期后缀是good enough。如果我必须在同一天同样命名文件,我会

<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>a
<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>b
<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>...

答案 12 :(得分:0)

我会使用文件路径+提升_INCLUDED后缀加上现在广泛支持的#pragma once

在很多编辑器中(对我而言,它是崇高的)你也可以为此定义一些宏/片段。

这是为你做的一个:

<snippet>
    <content><![CDATA[
#ifndef ${1:${TM_FILEPATH/(.*\/(include|src))*([^a-zA-Z0-9_]+)*([a-zA-Z0-9_]+)([.])*([a-zA-Z0-9_]+)*/\U$4_$6/ig}_INCLUDED}
#define $1
#pragma once


$0


#endif // $1
]]></content>
    <tabTrigger>incguard</tabTrigger>
    <description>include guard</description>
</snippet>

所以yourproject/include/yourlib/yourfile.hpp

变为YOURLIB_YOURFILE_HPP_INCLUDED

另外一个外部源代码样式检查工具可以通过这种方式轻松跟踪警卫的一致性。