C++ C+中的标题保护问题+;

C++ C+中的标题保护问题+;,c++,header,macros,C++,Header,Macros,我对写自己的标题还不熟悉,但由于需要,我必须学习 我正在写一个头球,我正在尝试摸索头球后卫。在包含的头文件之前和之后有一个或两个下划线有区别吗 以这个假设的例子:x.h //x.h #ifndef __X_H_INCLUDED__ #define __X_H_INCLUDED__ //functions n stuff #endif 与: //x.h #ifndef _X_H_INCLUDED_ #define _X_H_INCLUDED_ //functions n stuff #endif

我对写自己的标题还不熟悉,但由于需要,我必须学习

我正在写一个头球,我正在尝试摸索头球后卫。在包含的头文件之前和之后有一个或两个下划线有区别吗

以这个假设的例子:x.h

//x.h
#ifndef __X_H_INCLUDED__
#define __X_H_INCLUDED__
//functions n stuff
#endif
与:

//x.h
#ifndef _X_H_INCLUDED_
#define _X_H_INCLUDED_
//functions n stuff
#endif

一个比另一个对吗?有区别吗

根据
C++11 17.6.4.3.2全局名称
(尽管此限制已存在一段时间):

某些名称和函数签名集始终保留给实现:

  • 包含双下划线或以下划线开头,后跟大写字母的每个名称都保留给实现以供任何使用
  • 每个以下划线开头的名称都保留给实现,以用作全局命名空间中的名称
所以,如果你想让你的软件具有便携性,那么你真的应该两者都不使用,尽管如此,很多人确实使用这两种软件

使用
GUARD_X_H
X_H_include
之类的工具会“更安全”,当然,您仍然需要警惕冲突。您可能会采用Java方式,最终得到如下宏:

AU_COM_POWERFIELD_DATASTRUCTURES_TREES_BALANCED_BTREE_H
只要宏名称低于实现限制(从内存中至少为1024个字符)


可选地,如果你想牺牲可移植性(但是它在很多编译器中支持的话不多,那么你可以查看<代码> > * PrimMA曾经,在这里你不必担心出现唯一的名字。

< P>从2003 C++标准(这些规则仍然适用):

17.4.3.2.1全局名称[lib.Global.names]

某些名称和函数签名集始终保留给 实施:

每个名称都包含一个双下划线(u u)或以 下划线后跟大写字母(2.11)保留给 实现任何用途。 以下划线开头的每个名称 保留给实现,以便在全局 namespace.165)此类名称也保留在namespace::std中 (17.4.3.1)


我喜欢遵循与项目结构相匹配的include-guard的特定结构

#ifndef PROJECT_PATH_TO_FILE_HPP
// etc. etc.
因此,如果项目名为“skittles”,且标题路径为
taste/the/rainbow.hpp
,则我的include guard变为:

#ifndef SKITTLES_TASTE_THE_RAINBOW_HPP
// etc. etc.
这很有效,您只需小心名称与文件名和目录的冲突。例如,项目根目录中的一个文件名为
foo\u bar.hpp
,另一个文件名为
foo/bar.hpp
。这将导致必须解决的名称冲突

另一种选择是使用名称空间而不是路径:

#define PROJECT_NAMESPACE_MODULE_HPP

我还看到人们附加文件创建的日期和时间,或者使用UUID,为防止名称冲突增加进一步的安全性。

双下划线保留在实现中--在您自己的头文件中使用它们是未定义的行为,通常不是一个好主意。另外,请查看
#pragma once
没有前导下划线会是最好的。为什么不把它包括在内呢?@Anthony,pragmas就其定义而言,是不可移植的。当然,如果你愿意将自己局限于支持它的编译器(我想可能有很多:)。@paxdiablo根据链接的问题,有很多。我通常只使用一次
#pragma
,并包括警卫。