ヘッダーファイルと .cpp ファイルがあるのはなぜですか? [closed] 質問する

ヘッダーファイルと .cpp ファイルがあるのはなぜですか? [closed] 質問する

C++ にヘッダー ファイルと .cpp ファイルがあるのはなぜですか?

ベストアンサー1

C++ コンパイル

C++ でのコンパイルは、主に 2 つのフェーズで行われます。

  1. 1 つ目は、「ソース」テキスト ファイルをバイナリ「オブジェクト」ファイルにコンパイルすることです。CPP ファイルはコンパイルされたファイルであり、生の宣言またはヘッダーのインクルードによって入力されない限り、他の CPP ファイル (またはライブラリ) に関する情報なしでコンパイルされます。CPP ファイルは通常、.OBJ または .O「オブジェクト」ファイルにコンパイルされます。

  2. 2 番目は、すべての「オブジェクト」ファイルをリンクし、最終的なバイナリ ファイル (ライブラリまたは実行可能ファイル) を作成することです。

HPP はこのプロセス全体の中でどこに位置づけられるのでしょうか?

かわいそうな孤独な CPP ファイル...

各 CPP ファイルのコンパイルは他のすべての CPP ファイルから独立しています。つまり、次のように A.CPP に B.CPP で定義されたシンボルが必要な場合、

// A.CPP
void doSomething()
{
   doSomethingElse(); // Defined in B.CPP
}

// B.CPP
void doSomethingElse()
{
   // Etc.
}

A.CPP には "doSomethingElse" が存在することを知る方法がないため、コンパイルされません... A.CPP に次のような宣言がない限り:

// A.CPP
void doSomethingElse() ; // From B.CPP

void doSomething()
{
   doSomethingElse() ; // Defined in B.CPP
}

次に、同じシンボルを使用する C.CPP がある場合は、宣言をコピー/貼り付けます...

コピー/貼り付け注意!

はい、問題があります。コピー/ペーストは危険であり、維持も困難です。つまり、コピー/ペーストせずにシンボルを宣言する方法があればすばらしいのですが... どうすればよいでしょうか? 一般に .h、.hxx、.h++、または C++ ファイルの場合は .hpp という拡張子が付いたテキスト ファイルをインクルードすることで実現できます。

// B.HPP (here, we decided to declare every symbol defined in B.CPP)
void doSomethingElse() ;

// A.CPP
#include "B.HPP"

void doSomething()
{
   doSomethingElse() ; // Defined in B.CPP
}

// B.CPP
#include "B.HPP"

void doSomethingElse()
{
   // Etc.
}

// C.CPP
#include "B.HPP"

void doSomethingAgain()
{
   doSomethingElse() ; // Defined in B.CPP
}

どのようにinclude機能しますか?

ファイルをインクルードすると、本質的にはその内容が解析され、CPP ファイルにコピー アンド ペーストされます。

たとえば、次のコードでは、A.HPP ヘッダーを使用します。

// A.HPP
void someFunction();
void someOtherFunction();

...ソースB.CPP:

// B.CPP
#include "A.HPP"

void doSomething()
{
   // Etc.
}

... 含めた後は次のようになります:

// B.CPP
void someFunction();
void someOtherFunction();

void doSomething()
{
   // Etc.
}

1 つ小さな質問ですが、なぜ B.HPP が B.CPP に含まれているのでしょうか?

現時点では、これは必要なく、B.HPP には関数doSomethingElse宣言があり、B.CPP にはdoSomethingElse関数定義 (それ自体が宣言) があります。しかし、より一般的なケースでは、B.HPP が宣言 (およびインライン コード) に使用され、対応する定義 (たとえば、列挙型、プレーンな構造体など) が存在しない可能性があるため、B.CPP が B.HPP からの宣言を使用する場合は、インクルードが必要になる可能性があります。全体として、ソースがデフォルトでヘッダーをインクルードすることは「良い趣味」です。

結論

C++ コンパイラはシンボル宣言のみを検索することができないため、ヘッダー ファイルが必要になります。そのため、それらの宣言を組み込むことで C++ コンパイラを支援する必要があります。

最後に一言: 複数のインクルードによって何も壊れないように、HPP ファイルのコンテンツの周囲にヘッダー ガードを配置する必要がありますが、全体として、HPP ファイルが存在する主な理由は上記で説明されていると思います。

#ifndef B_HPP_
#define B_HPP_

// The declarations in the B.hpp file

#endif // B_HPP_

あるいはもっとシンプルに(ただし標準ではない)

#pragma once

// The declarations in the B.hpp file

おすすめ記事