20

プロジェクトにほとんど違いがないことはわかっていますが、C++ コードに #defined ヘッダー ガードを使用すると仮定すると、どの形式を使用しますか? たとえば、次のヘッダーがあるとしfoo.hppます。

#ifndef __FOO_HPP__
...

#ifndef INCLUDED_FOO_HPP
...

#ifndef SOME_OTHER_FORMAT

大文字の #defines のアイデアには賛成ですが、これらのガードの形式を決めることはできません。

4

13 に答える 13

20

ヘッダー名だけが危険であることが証明されているため、インクルードガードには常に名前空間または相対パスを含めました。

たとえば、コードのどこかに2つのファイルがある大きなプロジェクトがあります

/myproject/module1/misc.h
/myproject/module2/misc.h

したがって、インクルードガードに一貫した命名スキーマを使用すると、両方のファイルで定義されてしまう可能性があり_MISC_HPP__ます(このようなエラーを見つけるのは非常に面白いです)。

だから私は

MYPROJECT_MODULE1_MISC_H_
MYPROJECT_MODULE2_MISC_H_

これらの名前はかなり長いですが、二重の定義の苦痛と比較すると、それだけの価値があります。

別のオプションとして、コンパイラー/プラットフォームに依存しない場合は、#pragmaを1回探すことができます。

于 2008-11-24T18:41:33.940 に答える
14

名前の衝突を本当に回避するために、GUIDを使用します。

#ifndef GUARD_8D419A5B_4AC2_4C34_B16E_2E5199F262ED
于 2008-11-24T18:39:17.063 に答える
14

いつも使っていますINCLUDED_FOO_HPP

ダブルアンダースコアで物事を開始することは予約されているため、ダブルアンダースコアは使用しません。

于 2008-11-24T18:32:49.463 に答える
10

個人的には、ファイル名FOO_HPPを使用します。GoogleはSRC_ENGINE_FAST_HPPのようなパス全体を使用します。

名前と関数シグネチャの特定のセットは、常に実装用に予約されています。

  • 二重下線(_ _)を含む、または下線で始まり、その後に大文字(2.11)が続く各名前は、あらゆる用途のために実装用に予約されています。
  • アンダースコアで始まる各名前は、グローバル名前空間で名前として使用するために実装に予約されています。

17.4.3.1.2/1

于 2008-11-24T18:41:05.440 に答える
4

私はこのフォーマットを好みます:

#ifndef FOO_HPP
#define FOO_HPP

/* ... */

#endif // FOO_HPP
  • ヘッダーガードに複雑な条件を使用することはほとんど意味がないため、#if!defined(...)の代わりに単純な#ifndef 。
  • 識別子をヘッダーガードとしてマークする_HPP部分。
  • このような識別子(2つのアンダースコアまたは1つのアンダースコアと大文字で始まる)は実装用に予約されているため、先頭にアンダースコアはありません。
  • 基本部分は、ファイル名FOOだけです。ただし、再利用するライブラリコードについては、最初に別の部分を追加することをお勧めします。これは通常、名前空間または「モジュール」名を含むものMYLIB_FOO_HPPであり、名前の競合を回避するのに役立ちます。
于 2008-11-24T18:40:34.987 に答える
3

Visual StudioまたはMicrosoftコンパイラを使用している場合は、プラグマ方式を使用してください

#pragma once
于 2008-11-24T18:39:04.303 に答える
3

私が使う

 #if !defined(FOO_HPP_INCLUDED)

defined|| が許可されているため、最新の構文を好みます。&& 演算子 (ここでは使用されていませんが)。

また

 #ifndef __FOO_HPP__

先頭のアンダースコアが予約されているため、技術的には違法です。

于 2008-11-24T18:34:53.890 に答える
1

また、次のようなものを常に使用してきました。

#ifndef FOO_HPP
#define FOO_HPP 1

...

#endif

ほとんどの人が言及しているように、実装による内部使用のために C++ 標準によって予約されているため、2 つのアンダースコアをシンボルの先頭に追加しないでください。

ヘッダー インクルードに関する考慮事項については、John Lakos の優れた本「Large Scale C++ Software Design」( Amazon リンク- スクリプト キディ リンク ナチスのためにサニタイズ) を参照してください。

HTH

乾杯、

ロブ

于 2008-11-24T19:44:49.210 に答える
1

いつも利用しています

#ifndef FOOBAR_CPP
于 2008-11-24T18:36:33.340 に答える
1

私が自分の時間に対して支払われていて、まだ会社の基準がない場合、私は次のように使用します:

#ifndef path_to_file_h
#define path_to_file_h

小文字の理由は、ファイル名をコピーして貼り付けたり、スラッシュをアンダースコアに置き換えたりするのが簡単だからです。#ifndef の理由は、#define とうまく調和しているため、シンボルが同じであることを簡単に確認できます。ただし、GUID のアイデアは気に入っているので、試してみるかもしれません。

時間の対価が支払われず、コードを公開していないときは、#pragma once. 他のほとんどの移植性の問題とは異なり、インクルード ガードを後から追加するのは今と同じくらい簡単です。また、コード ベースについて何も知らない人でも実行できます (たとえば、1 年後の私、または私のコードを送った無実のプログラマーなど)。ので、YAGNI が適用されます。

于 2008-11-25T02:18:26.997 に答える
0

私が使う

<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>

また

<FILENAME_IN_ALL_CAPS>_INCLUDED_<YYYYMMDD>

フォルダ階層との同期を維持するのは面倒です(リファクタリングの友)、GUIDは面倒です、日付のサフィックスで十分です。同じ日に同じ名前のファイルを作成する必要がある場合は、

<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>a
<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>b
<FILENAME_IN_ALL_CAPS>_<YYYYMMDD>...
于 2011-12-15T14:13:26.033 に答える
0

私はファイルパス+ブースト_INCLUDEDサフィックスに加えて、最近広くサポートされている#pragma once

多くのエディター (私にとっては崇高です) では、このためにいくつかのマクロ/スニペットを定義することもできます。

これがあなたのためにそれを行うものです:

<snippet>
    <content><![CDATA[
#ifndef ${1:${TM_FILEPATH/(.*\/(include|src))*([^a-zA-Z0-9_]+)*([a-zA-Z0-9_]+)([.])*([a-zA-Z0-9_]+)*/\U$4_$6/ig}_INCLUDED}
#define $1
#pragma once


$0


#endif // $1
]]></content>
    <tabTrigger>incguard</tabTrigger>
    <description>include guard</description>
</snippet>

それでyourproject/include/yourlib/yourfile.hpp

になるYOURLIB_YOURFILE_HPP_INCLUDED

追加の外部ソース コード スタイル チェッカー ツールを使用すると、この方法でガードの一貫性を簡単に追跡できます。

于 2014-06-29T20:09:12.770 に答える
0

私は使用する傾向があります:

#ifndef FILE_DATE_H_

(_H_ を _HPP_ などの適切な拡張子に置き換えます)。日付スタンプは、他の方向/ライブラリの他の同じ名前のヘッダーとの衝突を避けるためのものです。

最終的には次のようになります。

#ifndef SOMEFILE_20082411_H_
于 2008-11-24T19:50:49.213 に答える