C++ 包含守卫通常是如何命名的?我经常看到这个:
#ifndef FOO_H
#define FOO_H
// ...
#endif
但是,我认为这不是很直观。如果没有看到文件名,就很难知道它的FOO_H
用途和它的名称所指的内容。
什么是最佳实践?
C++ 包含守卫通常是如何命名的?我经常看到这个:
#ifndef FOO_H
#define FOO_H
// ...
#endif
但是,我认为这不是很直观。如果没有看到文件名,就很难知道它的FOO_H
用途和它的名称所指的内容。
什么是最佳实践?
我个人遵循 Boost 的建议。它可能是最大的高质量 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
并且“曾经”是默认行为......)
根据我自己的经验,约定是在包含它们的头文件之后命名包含保护,但名称全部大写并且句点替换为下划线。
就这样test.h
变成了TEST_H
。
现实生活中的示例包括 Qt Creator,它在自动生成类头文件时遵循此约定。
直接取自谷歌的风格指南:
所有头文件都应该有#define 保护以防止多次包含。符号名称的格式应为 <PROJECT>_<PATH>_<FILE>_H_。为了保证唯一性,它们应该基于项目源代码树中的完整路径。例如,项目 foo 中的文件 foo/src/bar/baz.h 应该具有以下保护:
#ifndef FOO_BAR_BAZ_H_ #define FOO_BAR_BAZ_H_ ... #endif // FOO_BAR_BAZ_H_
我在自己的项目中使用这种风格。
查看#include 是您的标头的代码。
如果是这样的:
#include "mylib/myheader.h"
mylib/myheader.h
已经是一个唯一的名称。只需大写并替换 / 和 。和 _
#define MYLIB_MYHEADER_H
如果您的包含路径上有两个与包含路径具有相同名称的标头,则您已经在该级别发生了冲突。
替换FOO_H
为FOO_H_INCLUDED
,它更清晰。
正如其他人之前提到的,一个非常常见的约定是使用大写版本的名称,并将点替换为下划线: foo.h -> FOO_H
但是,这可能会导致名称与简单和/或通用名称发生冲突。因此,非空 Visual C 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
我通常使用类似FOO_H_INCLUDED_
. 一些(Microsoft)标头看起来很像 GUID 的字符串表示形式,但我从来不需要如此复杂的东西。
通常人们通过文件名来做这件事,这样每个文件的代码只会被编译和添加一次。你可以随心所欲地制作 FOO_H,但我曾经编码或看到的几乎所有东西都使用了文件名。只要确保它是唯一的,因为您不希望您的 FOO_H 与其他人的 FOO_H 冲突。
我通常会查看现在是什么时间,然后将其附加到它的末尾,即FOO_H_248
,这是一种额外的预防措施,无论如何您都不必记住它,因此您不必担心它是神秘的事实。