Naming Include Guards

2019-01-07 23:29发布

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?

9条回答
时光不老,我们不散
2楼-- · 2019-01-07 23:50

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.

查看更多
女痞
3楼-- · 2019-01-07 23:55

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...)

查看更多
聊天终结者
4楼-- · 2019-01-08 00:00

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楼-- · 2019-01-08 00:06

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.

查看更多
Animai°情兽
6楼-- · 2019-01-08 00:09

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.

查看更多
再贱就再见
7楼-- · 2019-01-08 00:14

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
查看更多
登录 后发表回答