2011-02-01 44 views
16

C++如何包含通常命名的警卫?我倾向于看到很多:命名包含警卫

#ifndef FOO_H 
#define FOO_H 

// ... 

#endif 

但是,我不认为这很直观。在没有看到文件名的情况下,很难分辨出FOO_H的名称和名称是什么。

什么被认为是最佳实践?

+2

虽然这个名字可能或多或少直观的,但事实是,与一些经验,你停止阅读这些线路。眼睛和大脑习惯了`#ifdef blahblah ...`,我几乎没有真正读过什么是检查,它是一个包括后卫。 – 2011-02-01 20:43:53

+3

对此有点有用的观点:http://stackoverflow.com/questions/1744144/adding-an-include-guard-breaks-the-build/1744302#1744302 – 2011-02-01 20:48:54

+0

任何做C++开发的人最好习惯于识别标头守卫很快。它会一直遵循你所看到的标准。 “最佳”练习(在引号中是因为它是必需的)是将ifndef放在第一位,紧跟在后面的定义,并在文件末尾完成。我建议你尽快认识到这一点。 – 2011-02-01 20:50:56

回答

15

从我自己的经验来看,约定是在包含它们的头文件之后命名包含守护程序,但名称全部用大写字母表示,而句号用下划线替换。

所以test.h变成TEST_H

这种现实生活中的例子包括Qt Creator,它在自动生成类头文件时遵循此惯例。

+4

将FILENAME_H用作包含名称是很好的,因为您将所有项目和所有库的所有文件保存在同一目录中,而无需任何子目录,因此您知道它们永远不会有冲突的文件名... – 2011-02-01 20:57:35

+2

虽然这是常见做法,它可能不够好,取决于你的店铺用#defines和其他名称做什么。 – 2011-02-01 20:58:02

1

我通常使用类似FOO_H_INCLUDED_的东西。一些(Microsoft)头文件看起来很像GUID的字符串表示形式,但我从不需要任何相当详细的内容。

3

FOO_H替换为FOO_H_INCLUDED它更清晰。

1

通常情况下,人们通过文件名来做到这一点,以便每个文件的代码只被编译和添加一次。无论你想要什么,你都可以做FOO_H,但几乎所有我编码或看过的东西都使用了文件名。只要确保它是独一无二的,因为你不希望你的FOO_H与其他人的FOO_H发生冲突。

10

直接从google's style guide摘自:

所有的头文件应该有#定义 守卫防止多包容。 符号名称的格式应为 为< PROJECT> _ < PATH> _ < FILE> _H_。到 保证唯一性,它们应该是 根据项目的 源树中的完整路径。例如,文件 富/ src目录/酒吧/项目foo中 baz.h应具有以下后卫:

#ifndef FOO_BAR_BAZ_H_ 
#define FOO_BAR_BAZ_H_ 
... 
#endif // FOO_BAR_BAZ_H_ 

我在自己的项目中使用这种风格。

+5

虽然一般来说谷歌编码标准是我见过的最糟糕的一种,但我使用名称空间作为前缀。如果在多个命名空间中有相同名称的东西,这是绝对必要的。 – 2011-02-01 20:48:36

1

我通常看看现在是几点,只是将其附加到它的末尾,即FOO_H_248,这是一个额外的预防措施,无论如何你永远不必记住它,所以你不必担心事实上它是神秘的。

2

正如其他人前面提到的,一个很普通的惯例是使用名字的大写形式,并通过点替换为下划线:foo.h中 - > FOO_H

然而,这会导致名称冲突与简单和/或通用名称。由于这个原因,像在非空的Visual C++项目stdafx.h中自动生成的标题附加一些随机字符串,如:

#ifndef FOO_H__NsknZfLkajnTFBpHIhKS 
#define FOO_H__NsknZfLkajnTFBpHIhKS 
#endif 

http://www.random.org/strings/是此有用的随机发生器。

而且,如果该文件是一些子模块的一部分,或者其内容驻留在一个特定的命名空间,我倾向于将它添加到后卫太:

#ifndef SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS 
#define SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS 

namespace somecomponent 
{ 
    ... 
} 

#endif 
4

看那个#包括是你的头的代码。

如果是这样的:

#include "mylib/myheader.h" 

mylib/myheader.h已经是唯一的名称。只是大写和替换/和。与_

#define MYLIB_MYHEADER_H 

如果你有你的包括相对于包含路径的同名路径两个头,你已经在该级别的碰撞。

16

我个人遵循Boost的建议。它可能是C++库中质量最好的C++库中最大的一个,它们没有问题。

它是这样:

<project>_<path_part1>_..._<path_partN>_<file>_<extension>_INCLUDED 

// include/pet/project/file.hpp 
#ifndef PET_PROJECT_FILE_HPP_INCLUDED 

是:

  • 法律(由_[A-Z]注意,开始或含有__不是)
  • 容易产生
  • 保证唯一性(作为包括后卫)在一个项目中(否则你在同一个地方有两个文件)
  • 保证不会被用于其他任何(如果你最终另一个宏与INCLUDED你求战心切)

我读过有关GUID,但这些看起来很怪异。

而且很明显,我宁愿不是所有的编译器实现#pragma once(或更好,#pragma multiple和“一次”是默认的行为...)