C++ C+中的标题保护问题+;
我对写自己的标题还不熟悉,但由于需要,我必须学习 我正在写一个头球,我正在尝试摸索头球后卫。在包含的头文件之前和之后有一个或两个下划线有区别吗 以这个假设的例子:x.hC++ 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
#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
,并包括警卫。