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

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

Mary-Kate Olsen
リリース: 2024-12-22 19:37:11
オリジナル
554 人が閲覧しました

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 サイトの他の関連記事を参照してください。

ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート