ホームページ >バックエンド開発 >C++ >インクルード ガードが再帰的インクルードと複数のシンボル定義を防止できないのはなぜですか?

インクルード ガードが再帰的インクルードと複数のシンボル定義を防止できないのはなぜですか?

Mary-Kate Olsen
Mary-Kate Olsenオリジナル
2024-12-22 19:37:11555ブラウズ

Why Are My Include Guards Failing to Prevent Recursive Inclusion and Multiple Symbol Definitions?

インクルード ガードが再帰的インクルードと複数のシンボル定義を防止しないのはなぜですか?

最初の質問:

なぜインクルードしないのですか?ヘッダファイルを相互再帰から保護するガードinclusion?

インクルードガードは仕事をしています。この問題は、相互にインクルードするヘッダー内のデータ構造の定義間の依存関係から発生します。

たとえば、a.h と b.h に次の内容が含まれているとします。

// a.h
#ifndef A_H
#define A_H
#include "b.h"
struct A {...};
#endif

// b.h
#ifndef B_H
#define B_H
#include "a.h"
struct B {...};
#endif

インクルード ガードがないと、main.cpp は次のように動作しません。コンパイルの深さの制限によりコンパイルされます。

インクルード ガードを使用すると、無限再帰が防止されます。ただし、定義間の依存関係は残ります。

  • a.h のコンパイル中に、プリプロセッサは #include "b.h" に遭遇し、それを処理します。
  • b.h の処理中に、#include "a.h" に遭遇し、
  • これにより、B を定義する前に A を定義する必要があるという依存関係が作成されます。

これを解決するには、必要なヘッダーで前方宣言を使用します。

// b.h
#ifndef B_H
#define B_H
struct A; // Forward declaration
struct B {...};
#endif

2 番目の質問:

なぜインクルードされないのか複数の定義を防ぐガード?

ガードを含めると再定義を防ぐことができます

たとえば、header.h:

#ifndef HEADER_H
#define HEADER_H
int f() {...};
#endif

が複数の翻訳単位 (source1.cpp やsource2.cpp など) に含まれる場合:

// source1.cpp
#include "header.h"

// source2.cpp
#include "header.h"

リンカは、別のオブジェクトで同じ定義を認識するため、f() の複数の定義について文句を言います。

これを解決するには、次の方法を使用します。

  • inline キーワード: 関数本体をインライン化するようにコンパイラーに指示し、リンカーなしで複数の定義を可能にします。エラー。
  • static キーワード: 関数に内部リンケージを与え、プライベート キーワードを作成します。翻訳単位ごとにコピーします。
  • 名前のない名前空間: 名前のない名前空間で関数を宣言すると内部結合が与えられ、複数の定義が防止されます。

以上がインクルード ガードが再帰的インクルードと複数のシンボル定義を防止できないのはなぜですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。