可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
How are C++ include guards typically named? I tend to see this a lot:
#ifndef FOO_H
#define FOO_H
// ...
#endif
However, I don't think that's very intuitive. Without seeing the file name it's difficult to tell what FOO_H
is there for and what its name refers to.
What's considered best practice?
回答1:
From my own experience, the convention is to name the inclusion guards after the header file containing them with the exception that the name is all in caps and the period is replaced with an underscore.
So test.h
becomes TEST_H
.
Real life examples of this include Qt Creator, which follows this convention when auto-generating class header files.
回答2:
I personally follow Boost's recommendation. It's perhaps one of the largest collection of C++ libraries of good quality around and they don't have problem.
It goes like:
<project>_<path_part1>_..._<path_partN>_<file>_<extension>_INCLUDED
// include/pet/project/file.hpp
#ifndef PET_PROJECT_FILE_HPP_INCLUDED
which is:
- legal (note that beginning by
_[A-Z]
or containing __
is not)
- easy to generate
- guaranteed to be unique (as a include guard) within a project (else you have two files at the same place)
- guaranteed not to be used for anything else (if you end another macro with
INCLUDED
you're spoiling for a fight)
I've read about GUID but those look weird.
And obviously I'd rather than all compilers implement #pragma once
(or better, #pragma multiple
and "once" be the default behavior...)
回答3:
Taken directly from google's style guide:
All header files should have #define
guards to prevent multiple inclusion.
The format of the symbol name should
be <PROJECT>_<PATH>_<FILE>_H_. To
guarantee uniqueness, they should be
based on the full path in a project's
source tree. For example, the file
foo/src/bar/baz.h in project foo
should have the following guard:
#ifndef FOO_BAR_BAZ_H_
#define FOO_BAR_BAZ_H_
...
#endif // FOO_BAR_BAZ_H_
I use this style in my own projects.
回答4:
Look at the code that #include's your header.
If it is something like:
#include "mylib/myheader.h"
mylib/myheader.h
is already a unique name. Just capitalize and replace / and . with _
#define MYLIB_MYHEADER_H
If you have two headers on your include path with the same name relative to the include path, you already have a collision at that level.
回答5:
Replace FOO_H
with FOO_H_INCLUDED
and it's clearer.
回答6:
As others mentioned before, a very common convention is to use the uppercase version of the name, and the dot replaced by an underscore: foo.h -> FOO_H
However, this can lead to name collisions with simple and/or common names. For this reason, autogenerated header like the stdafx.h in non-empty Visual C C++ projects append some random string, like:
#ifndef FOO_H__NsknZfLkajnTFBpHIhKS
#define FOO_H__NsknZfLkajnTFBpHIhKS
#endif
http://www.random.org/strings/ is a useful random generator for this.
Also, if the file is part of some submodule, or its contents reside in one specific namespace, I tend to add that to the guard too:
#ifndef SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS
#define SOMECOMPONENT_FOO_H__NsknZfLkajnTFBpHIhKS
namespace somecomponent
{
...
}
#endif
回答7:
I normally use something like FOO_H_INCLUDED_
. A few (Microsoft) headers have what looks a lot like a string representation of a GUID, but I've never needed anything quite that elaborate.
回答8:
Usually people do that by file name so that each file's code only gets compiled and added once. You could make FOO_H whatever you want, but almost everything I've ever coded or seen has used the file name. Just make sure it's unique because you don't want your FOO_H conflicting with someone else's FOO_H.
回答9:
I usually look what time it is and just append that to the end of it, i.e. FOO_H_248
, it's an extra precaution, and you'll never have to remember it anyway, so you don't need to worry about the fact that it's cryptic.