17

iostreamまたは他のヘッダー ファイルをファイルに 2 回インクルードするとどうなりますか? コンパイラがエラーをスローしないことはわかっています。

コードは 2 回追加されますか、それとも内部で何が起こりますか?

ヘッダー ファイルをインクルードすると、実際にはどうなるでしょうか。

4

5 に答える 5

23

インクルード ガードは、ファイルの内容がコンパイラによって実際に 2 回見られるのを防ぎます。

インクルード ガードは基本的に、ヘッダー ファイルの最初と最後にあるプリプロセッサの条件付きディレクティブのセットです。

#ifndef SOME_STRING_H
#define SOME_STRING_H

//...

#endif 

ファイルを 2 回インクルードすると、最初のラウンド マクロSOME_STRING_Hは定義されないため、ファイルの内容が処理され、コンパイラによって表示されます。ただし、is の#ifdef後の最初のものは定義されており、次回はヘッダー ファイルの内容がコンパイラによって認識されないためです。#defineSOME_STRING_H

衝突を避けるために、インクルード ガードで使用されるマクロの名前は、ヘッダー ファイルの名前に依存します。

于 2012-10-17T07:09:12.997 に答える
4

ヘッダー ファイルは単純な獣です。何#include <header>が起こるかというと、header基本的にの内容がファイルにコピーアンドペーストされることです。ヘッダーが複数回含まれinclude guardsないようにするために使用されます。これが、ほとんどのヘッダー ファイルで次のようなものが表示される理由です。

#ifndef SOME_HEADER_FILE_GUARD 
#define SOME_HEADER_FILE_GUARD

//Contents of Header

#endif
于 2012-10-17T07:11:23.253 に答える
2

場合によります。を除いて<assert>、標準では、標準ヘッダーの 2 番目 (およびそれ以降) のインクルードはノーオペレーションである必要があります。ただし、これはヘッダーの特性です。コンパイラは、(少なくとも概念的には) インクルードに遭遇するたびに、すべてのヘッダー テキストを読み取ってインクルードします。

このような場合に複数の定義を回避するための標準的な方法は、インクルード ガードを使用することです。ヘッダー内のすべての C++ コードは、次のようなもので囲まれます。

#ifndef SPECIAL_NAME
#define SPECIAL_NAME
//  All of the C++ code here
#endif SPECIAL_NAME

明らかに、各ヘッダーには異なる名前が必要です。アプリケーション内では、通常、ファイル名と場所に基づいて規則を確立できます。のようなものsubsystem_filenameで、C++ シンボル (ファイル名でそれらを使用している場合) で許可されていない文字がマップされています (非常に多くの場合、すべてが大文字になります)。ライブラリの場合、ベスト プラクティスは、適度に長いランダムな文字列を生成することです。はるかに頻繁に (実装の品質の観点からは確かに劣っていますが)、すべてのそのようなシンボルが文書化されたプレフィックスで始まることを確認することです。

もちろん、システム ライブラリはここで予約済みのシンボル (たとえば、アンダースコアで始まり、大文字が続くシンボル) を使用して、競合がないことを保証できます。または、まったく異なる実装依存の手法を使用することもできます。たとえば、Microsoft はコンパイラ拡張機能を使用してい#pragma onceます。g++ は常にで始まるインクルード ガードを使用します_GLIBCXX(これはユーザー コードでは正当なシンボルではありません)。これらのオプションは、必ずしも利用できるとは限りません。

于 2012-10-17T08:51:58.863 に答える
2

次の行に沿ったプリプロセッサ コードにより、単純にスキップされます。

#ifndef MY_HEADER_H
#define MY_HEADER_H

<actual header code here>

#endif

したがって、2 回含めると、 thenMY_HEADER_Hは既に定義されており、#ifndefとの間のすべて#endifがプリプロセッサによってスキップされます。

于 2012-10-17T07:10:14.513 に答える