简体   繁体   English

C ++ #ifndef包含文件,为什么所有大写文件都用于头文件?

[英]C++ #ifndef for include files, why is all caps used for the header file?

I wonder why the name after the #ifndef directive is always all caps and don't seem to match the name of the actual header file? 我想知道为什么#ifndef指令之后的名字总是全部大写并且似乎与实际头文件的名称不匹配? What are the rules surrounding this? 这有什么规则? I've been looking around the webs but, I haven't found any explanation for this. 我一直在寻找网络,但我没有找到任何解释。 If my header file is called myheader.h would it then be ok to use: 如果我的头文件名为myheader.h,那么可以使用:

#ifndef MYHEADER

If so, why? 如果是这样,为什么? What are the rules? 规则是什么?

These are preprocessor symbols and have no such rules. 这些是预处理程序符号,没有这样的规则。 (as long as they match the #defines in the headers) (只要它们与标题中的#defines匹配)

However, convention is to use all-caps for preprocessor symbols. 但是,惯例是对预处理程序符号使用全大写。

There's no "rule", there are just conventions. 没有“规则”,只有惯例。 The first and most used convention is that all precompiler macros are all uppercase, so header guards too should be all uppercase. 第一个也是最常用的约定是所有预编译宏都是大写的,所以标题保护也应该都是大写的。

As for the macro name, what I use (and what most of the code I've seen uses) is just the name of the header (as said, turned to all uppercase) including extension, replacing the dot with an underscore, followed by _INCLUDED . 至于宏名称,我使用的(以及我看到的大多数代码使用的)只是标题的名称(如上所述,转为全部大写),包括扩展名,用下划线替换点,然后是_INCLUDED

#ifndef MYHEADER_HPP_INCLUDED
#define MYHEADER_HPP_INCLUDED
// ...
#endif

Note that many prepend such identifiers with an underscore or a double underscore, but it's not good practice, since the standard specifies that identifiers beginning (or containing) double underscores and those beginning with a single underscore followed by an uppercase letter are reserved for compiler/library-specific stuff (eg __declspec in VC++ or macros used in the standard headers) at all scopes; 请注意,许多前缀此类标识符带有下划线或双下划线,但这不是一种好的做法,因为标准指定标识符开头(或包含)双下划线,以及以单个下划线后跟大写字母开头的标识符保留给编译器/所有范围内特定于库的东西(例如VC ++中的__declspec或标准头中使用的宏); all the other identifiers beginning with a single underscore are reserved at the global scope. 以单个下划线开头的所有其他标识符都保留在全局范围内。 So such identifiers shouldn't be used to avoid collisions. 因此,不应使用此类标识符来避免冲突。

More info on this stuff here . 这个东西更多信息在这里

It's not required to be all caps. 它不需要全部大写。 It's just the common convention. 这只是常见的惯例。 I usually use something like #ifndef MYHEADER_H_INCLUDED . 我经常使用像#ifndef MYHEADER_H_INCLUDED这样的东西。

Google for " include guard " to find what the thing is actually about. 谷歌为包括警卫找到了实际上的东西。

About the all-caps: It's a convention for macros to be in all-upper-case. 关于全部大写:宏是一种全局大写的惯例 The reason is that macros are processed by the preprocessor, an arcane text processing tool, that knows nothing of C++, and is best shut out of common identifiers, lest it tramples all over them, creating a big mess. 原因是宏是由预处理器处理的,这是一个神秘的文本处理工具,对C ++一无所知,最好不要使用常见的标识符,以免它遍及它们,造成一大堆混乱。

The idea is to make sure your header file is only read once during build. 我们的想法是确保您的头文件在构建期间只读取一次。 The idiom to accomplish that is the structure: 实现这个的成语是结构:

   #ifndef _SOME_UNIQUE_NAME
   #define _SOME_UNIQUE_NAME
   /* The actual header code */
   #endif

This means that you should choose a name that you are pretty sure will be unique and is a valid identifier for #ifndef. 这意味着您应该选择一个您非常确定将是唯一的名称,并且该名称是#ifndef的有效标识符。 You should also make sure that the identifier is not used in actual code or confused with a variable or something. 您还应确保标识符未在实际代码中使用或与变量或其他内容混淆。 Having an upper case tag marks the idiom clearly. 具有大写标记清楚地标记了成语。 Besides that, it is merely conventions not language that dictate that choice. 除此之外,仅仅是惯例而不是决定选择的语言。 Visual Studio's wizards generates a GUID like identifier for. Visual Studio的向导生成类似于标识符的GUID。 Sone compilers support #pragma once that have the same effect. Sone编译器支持#pragma一次具有相同的效果。

您可以使用任何您想要的名称,但是您希望使其唯一,以便不会在标题之外定义值,因此使用带有大写的标题名称只是一个很好的约定来确保它。

It's completely subjective and there are no enforced rules other than those normally associated with the character set for naming pre-processor macros. 它完全是主观的,除了通常与用于命名预处理器宏的字符集相关的规则之外,没有强制规则。 It's conventional for macros to be defined in upper case. 传统的宏以大写字母定义。 This tends to help them stand out in source code. 这有助于他们在源代码中脱颖而出。 A convention I tend to stick to is the strict capitalised version of the filename with the period replaced by an underscore and leading and trailing underscores. 我倾向于坚持的一个约定是文件名的严格大写版本,句点由下划线和前导和尾随下划线代替。 So, for a file called DataTableNameMangler.hpp the include guard would look like: 因此,对于名为DataTableNameMangler.hpp的文件,include guard看起来像:

#ifndef _DATATABLENAMEMANGLER_HPP_
#define _DATATABLENAMEMANGLER_HPP_

...

#endif // _DATATABLENAMEMANGLER_HPP_

There's no great reason for this though I strongly recommend for consistency that the name matches the filename exactly. 虽然我强烈建议使用名称与文件名完全匹配的一致性,但没有很好的理由。 I normally use a little class creator script to generate my initial classes. 我通常使用一个小类创建者脚本来生成我的初始类。 The following Bash snippet gives an idea: 以下Bash片段给出了一个想法:

#!/bin/bash
INC_GUARD_NAME="_${1^^*}_HPP_"
echo "#ifndef $INC_GUARD_NAME"
echo "#ifndef $INC_GUARD_NAME"
echo
echo "class $1 {};"
echo
echo "#endif // $INC_GUARD_NAME"

Thus: 从而:

$ ./makeclass.bash DataTableNameMangler
#ifndef _DATATABLENAMEMANGLER_HPP_
#ifndef _DATATABLENAMEMANGLER_HPP_

class DataTableNameMangler {};

#endif // _DATATABLENAMEMANGLER_HPP_

This is naturally just a very basic example. 这自然只是一个非常基本的例子。 Importantly, remember to put the comment before the guard name on the last line. 重要的是,请记住将注释放在最后一行的警卫名称之前。 #endif takes no parameters so the macro will be passed on to the C++ compiler which will complain about it if it's not commented. #endif没有参数,所以宏将被传递给C ++编译器,如果它没有被注释,它会抱怨它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM