我是新手编写自己的标题,但由于必要,我必须学习。
我正在写一个标题,而我正在试图控制标题。在包含的头文件之前和之后有一个或两个下划线之间有区别吗?
采用这个假设的例子:x.h
for
与
//x.h
#ifndef __X_H_INCLUDED__
#define __X_H_INCLUDED__
//functions n stuff
#endif
一个人或多或少比另一个人好吗?有区别吗?
答案 0 :(得分:8)
根据C++11 17.6.4.3.2 Global names
(虽然这种限制已经存在了一段时间):
某些名称和功能签名集始终保留给实现:
- 包含双下划线_ _或以下划线后跟大写字母开头的每个名称都保留给实现以供任何使用。
- 以下划线开头的每个名称都保留给实现,以用作全局命名空间中的名称。
所以你真的应该使用既不,如果你想让你的软件可移植,尽管如此,很多人做使用这两种。
它会更安全"虽然使用GUARD_X_H
或X_H_INCLUDED
之类的东西,当然,你仍然需要警惕冲突。您可以采用Java方式并最终使用以下宏:
AU_COM_POWERFIELD_DATASTRUCTURES_TREES_BALANCED_BTREE_H
只要你保持低于宏名称的实现限制(从内存中,至少1024个字符)。
或者,如果你想牺牲可移植性(但不是很多可移植性,因为它在很多编译器中得到支持),你可以查看#pragma once
,你在哪里和#39;不得不担心想出独特的名字。
答案 1 :(得分:2)
从2003 C ++标准(这些规则仍然适用):
17.4.3.2.1全局名称[lib.global.names]
始终保留某些名称和功能签名集 实施:
每个包含双下划线(_ _)或以。开头的名称 下划线后跟一个大写字母(2.11)保留给 实施任何用途。 每个名称以下划线开头 保留给实现以用作全局中的名称 namespace.165 165)这些名称也在namespace :: std中保留 (17.4.3.1)。
答案 2 :(得分:1)
我喜欢关注与项目结构相匹配的包含守卫的特定结构。
#ifndef PROJECT_PATH_TO_FILE_HPP
// etc. etc.
因此,如果该项目名称为“skittles”,并且标题的路径为taste/the/rainbow.hpp
,那么我的包含守护变为:
#ifndef SKITTLES_TASTE_THE_RAINBOW_HPP
// etc. etc.
这很好用,你只需要警惕与文件名和目录的名字冲突。例如,项目根目录中的一个文件名为foo_bar.hpp
,另一个文件位于foo/bar.hpp
。这将导致名称冲突,必须解决。
另一种选择是使用名称空间而不是路径:
#define PROJECT_NAMESPACE_MODULE_HPP
我还看到人们追加创建文件的日期和时间,或者使用UUID来进一步增加对名称冲突的安全性。