1. ホーム
  2. c++

[解決済み] .h ファイルで #ifndef CLASS_H と #define CLASS_H を使用し、.cpp で使用しない理由は何ですか?

2022-04-25 04:36:25

質問

と書いている人をよく見かけます。

class.h

#ifndef CLASS_H
#define CLASS_H

//blah blah blah

#endif

問題は、クラス関数の定義を含む.cppファイルについても、なぜそうしないのか、ということだ。

例えば main.cppmain.cpp には class.h . その class.h ファイルでは include はどのように main.cpp の中に何があるのかを知っています。 class.cpp ?

解決方法は?

まず、最初のお問い合わせに対応します。

に表示されている場合 .h ファイルを作成します。

#ifndef FILE_H
#define FILE_H

/* ... Declarations etc here ... */

#endif

これは、様々な理由で問題となるヘッダーファイルの複数回インクルードを防ぐためのプリプロセッサー技術です。 プロジェクトのコンパイル時に、それぞれの .cpp ファイルが(通常)コンパイルされます。 簡単に言うと、これはコンパイラがあなたの .cpp ファイルを開き、任意のファイル #included そして構文解析を行い、最終的に中間コードに変換し、最適化/その他のタスクを実行し、最終的にターゲットアーキテクチャ用のアセンブリ出力を生成するのです。 このため、もしファイルが #included 1つの .cpp そのため、そのファイル内に定義がある場合、変数を再定義したというコンパイラーエラーが発生します。 このファイルがコンパイルプロセスのプリプロセッサのステップで処理されるとき、最初にその内容に到達したとき、最初の2つの行は、もし FILE_H がプリプロセッサーに定義されています。 もしそうでなければ FILE_H との間のコードを処理し続けます。 #endif ディレクティブを使用します。 次にそのファイルの内容がプリプロセッサに表示されたときに FILE_H は false になるので、すぐに #endif の後に続けてください。 これにより、再定義エラーを防ぐことができます。

そして、2つ目の懸念に対応するためです。

C++のプログラミングでは、一般的に開発物を2つのファイルタイプに分けます。 1つは、拡張子が .h ヘッダーファイルは、通常、関数、クラス、構造体、グローバル変数、型定義、プリプロセッシングマクロ、定義などの宣言を提供します。 基本的に、ヘッダーファイルはコードに関する情報を提供するだけです。 次に .cpp このファイルには、関数、クラス・メンバー、定義が必要な構造体メンバー、グローバル変数などの定義が含まれます。 そのため .h ファイルはコードを宣言し .cpp ファイルはその宣言を実装しています。 このため、一般にコンパイル時には、それぞれの .cpp ファイルをオブジェクトに変換し、それらのオブジェクトをリンクします(なぜなら、1つの .cpp ファイルには、別の .cpp ファイル)を作成します。

これらの外部参照をどのように解決するかは、リンカーの仕事である。 コンパイラが main.cpp のコードに対する宣言を取得します。 クラス.cpp を含むことで class.h . 関数や変数がどのようなものかを知るだけでよいのです(これは宣言が与えてくれるものです)。 そのため main.cpp ファイルを何らかのオブジェクトファイル(これを main.obj ). 同様に class.cpp がコンパイルされ class.obj ファイルを作成します。 最終的な実行ファイルを作成するために、リンカーが起動され、これら2つのオブジェクトファイルを一緒にリンクします。 未解決の外部変数や関数がある場合、コンパイラはアクセスが発生する場所にスタブを配置します。 そして、リンカーはこのスタブを使って、リストアップされた別のオブジェクトファイルからそのコードや変数を探し、見つかった場合は、2つのオブジェクトファイルからコードを出力ファイルに結合し、スタブを関数や変数の最終位置に置き換えます。 このようにして、main.cpp のコードは、関数呼び出しや変数使用のために class.cpp で宣言されている場合のみです。 class.h .

参考になったでしょうか?