【问题标题】:Names used for include guards?用于包括警卫的名称?
【发布时间】:2018-05-15 17:15:49
【问题描述】:

在为他们的包含保护选择名称时,人们倾向于遵循哪些准则?我不明白为什么 .h 文件的名称会与包含保护中使用的名称略有不同。例如,我见过 sphere.h,然后是 #ifndef SPHERE_H_。我可以轻松地使用SPHERE_ 还是名称必须匹配?下划线也需要吗?

【问题讨论】:

  • 至少不要使用包含双下划线或以下划线开头后跟大写字母的名称 - 两者都是保留的。
  • 下划线不是必须的,但不要在开头使用一个或在任何地方连续使用两个。更多关于What are the rules about using an underscore in a C++ identifier?
  • 这不是#ifndef,而是header guardinclude guard
  • 我曾经使用 GUID,例如H123e4567_e89b_12d3_a456_426655440000。我有一个小程序可以批量生成它们。现在我只使用#pragma once。投票结束主要基于意见。
  • @JiveDadson — #pragma once 可能会失败,而且它不是标准 C++。

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


【解决方案1】:

要为头球后卫选择一个好名字,请考虑以下几点:

1) 名称必须是唯一的,所以要长而具体。这通常可以通过包含项目名称、模块名称、文件名和文件扩展名等内容来完成。

2) 确保您不使用为实现保留的名称。因此,以下划线后跟大写字母的名称已被淘汰,包含双下划线的名称、以 _t 结尾的名称等等也是如此。

3) 使名称对人类读者有意义。所以不要只生成一个 UUID 并使用它。

4) 约定要求您使用全部大写的宏来将它们与普通变量区分开来。

不需要下划线就这样,但由于您不能在宏名称中使用空格,因此下划线是保持可读性的好选择。

所以,恕我直言,项目 baz 中子模块 bar 中文件 foo.h 的良好保护名称是:BAZ_BAR_FOO_H。

【讨论】:

  • GUID 的主要问题是,当有人复制标头并修改 C++ 代码而不更新 GUID 时,它们最终成为 Gnot-UID。这在实现同级类时并不罕见。
  • @MSalters 我不建议使用 GUID,恰恰相反。
【解决方案2】:

大多数现代编译器都支持可以使用的#pragma once 指令。见:https://en.wikipedia.org/wiki/Pragma_once

【讨论】:

  • 但是,这个 pragma 还没有标准化
  • 而且始终值得注意的是它并不标准化,因为有一些突出的案例#pragma once 无法处理。
【解决方案3】:

用于包含守卫的符号的重要之处在于它们是独一无二的。这意味着不仅每个头文件(包括您的项目可能使用的任何库头)的包含保护都必须是唯一的,它们也不能与项目中任何地方使用的任何其他符号冲突。

人们有几种常见的方法来确保唯一性:

1) 使用<PROJECT_NAME>_<FILE_NAME> 之类的东西(即MYPROJECT_SPHERE_H

包含您的项目名称将有助于确保您的包含保护不会与您从某个库中包含的另一个“sphere.h”冲突。使用文件名和扩展名可以在向项目中添加新标头时轻松创建包含保护,并且不太可能在项目中的其他任何地方使用该名称(用于变量、函数等)。

2) 使用 UUID(即GUARD_0be96322_7238_49d2_a967_e8fd9907cca1

这是一种非常安全的方法,因为 UUID 非常不太可能发生冲突。但它更难阅读,这意味着您必须在创建新文件时挖掘 UUID 生成器。

【讨论】:

  • 一些程序员的编辑器可以生成包含 UUID 的守卫。
  • 包含 UUID 的标头守卫虽然读起来很痛苦,但并不能传达所保护内容的任何含义。
猜你喜欢
  • 2011-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-13
  • 2016-04-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多