0

この質問は、C++ インクルード ガードの命名規則について議論するいくつかの質問の 1 つです。その質問をしている人は、この命名規則について次のように考えています。

#ifndef FOO_H
#define FOO_H

// ...

#endif

は、それ自体を理解すると少し直感的ではなく (どういうFOO_H意味ですか?)、私は同意する傾向があります。

他の人は、より良い衝突回避のためにさらにものを追加する必要がなければ ( のようにPROJECTNAME_FOO_H_SDFFGH69876GF)、FOO_Hその目的がそのコンテキストから明らかであるため、名前は問題ありません (つまり、同じ名前のファイルの先頭にあり、インクルード ガードであることを明確にします)。

FOO_H複数のファイルが含まれないようにすることだけが目的であれば、これを購入することもできFOO_Hますが、ファイルの他の場所に必要な条件はありますか? 条件付きコンパイルは正当な理由になると思います。その場合、次のような名前を付けるとFOO_H_INCLUDEDより明確になります。

これに似た単純な使用法はありますか、それともインクルードガードの転用を避けるべきですか?

4

5 に答える 5

4

質問自体がおかしいと思います。インクルード ガードという用語は、複数の包含に対するガードの特定の使用における#defineおよびチェックを指します。#defined

もう少し一般的に考えると、定義と条件付きコンパイルは、プラットフォームに依存し、特定の状況でのみコンパイルされるコードのビットを書くなど、他のことに使用できます...

良いかどうFOO_HFOO_H_INCLUDEDは別として、私は常に後者が最も表現力に富んでいると言い、その後に戻って次のヘッダーviを入力します。繰り返しますが、他の質問のコメントで述べたように、次のパターンに慣れていきます。FOO_Hfoo.h

#ifndef XXXXXXXXX
#define XXXXXXXXX

#endif

ファイルの最初の2行と最後の行として、あなたは気づきます。あなたが同じ名前を再利用した場合、それは噛み付くまでです...

于 2011-02-01T21:52:32.383 に答える
1

時々、これを「実装」ヘッダー ファイルに使用します。ガードの実際の命名スキームは異なる場合があります。

#ifndef FOO_IMPL_H
#define FOO_IMPL_H

#ifndef FOO_H
#error Don't include this directly
#endif

// Ugly implementation of the stuff in foo.h, with an uncountable
// number of template and typename keywords

#endif 
于 2011-02-01T21:50:55.760 に答える
1

再利用の場合: ファイルの内容全体が ifndef/define/endif で囲まれている場合を除き、FOO_H実際にはファイルインクルード ガードではなく、ファイルの一部のみをガードしています。そのため、ファイル全体にちなんで名付けるべきではない可能性があります。同じファイルを再帰的に含めることは、これが発生する状況の 1 つです。

そうは言っても、たとえそうであっても、定義が何のためにあるのかはかなり明白であるべきだと思います(とにかく、あなたがやっているトリッキーなことは何であれ、ガーディングを含めるだけではないことはより明白です)。パターン ifndef FOO/define FOO や、単に ifndef FOO / define というパターンが見られる場合はどこでも、簡単なコメントを付けるだけで、FOO の意味が明確になる場合があります。

トークンが他の目的に使用される可能性があるかどうかが問題の一部である場合: インクルード ガードとして使用さFOO_Hれるファイルがどこかにある場合、それはおそらく誰かの、含むなどと衝突する可能性があると思います。愚かな例、しかし、ヘッダー ファイルで文字のプロパティを定義している場合、それらの一部が.uppercase.hUPPERCASE_Hrot13.h#define UPPERCASE_A ('N')_H

より現実的には、異なるディレクトリに同じベース名を持つインクルード ファイルを含むプロジェクトがありました。

したがって、コンテキストと転用の問題に関係なくFOO_H、インクルード ガードとしては使用しません。

于 2011-02-02T02:26:39.097 に答える
1

私の意見では、インクルード ガードはインクルード ガードであり、それ以上のものではありません。条件付きコンパイルが必要な場合は、別のものを定義します。コードをいじっていたら、通常はインクルード ガードを示している#if defined(FOO_H)ため、人々はこれを奇妙に感じると思います。_H

私が考えることができることの 1 つは、ファイルが既に含まれているかどうかを確認することです (当然です!) ので、自分でファイルを含める必要はありません。これがコンパイルを高速化するかどうかは、前方宣言または#pragma once

main.cpp で:

#include "bar.h" // comment this line to see the difference
#include "foo.h"

int main()
{
    return 0;
}

bar.h で:

#ifndef BAR_H
#define BAR_H

class BarClass
{
};

#endif

foo.h で:

#ifndef FOO_H
#define FOO_H

#if !defined(BAR_H)
#error bar h was not included // forgot how to do compiler warnings...
#include "bar.h" // we should include the file
#else
#error bar h was included // same thing, should be changed to warning
#endif

// do something with BarClass

#endif FOO_H
于 2011-02-01T21:54:01.997 に答える
1

条件付きコンパイルは正当な理由になると思います。その場合、 FOO_H_INCLUDED のような名前を付けるとより明確になります。

ここでは、前方宣言のみが必要であるが、ヘッダーが以前に含まれている場合は前方宣言をスキップしたい場合にヘッダーを含めることを避けるために、非常に狭い使用法を 1 つだけ見ます。

ただし、これは今日の C++ のコンパイルにおけるボトルネックではありません。また、常に前方宣言を行うか、常にヘッダーをインクルードするかについての追加の混乱は意味がありません。

何百行から何千行もの転送宣言が必要だったとしても、それが価値のあるものになるには、複数の場所でこれを維持するよりも、<iosfwd> のような専用のヘッダーを使用したほうがよいでしょう。 .

于 2011-02-01T22:03:00.623 に答える