C++ をファイルに分割すると、.cpp ファイルの代わりに .h ファイルが main 関数ファイルにインクルードされます。つまり、定義部分の代わりに宣言部分がインクルードされます。

C++ のサブファイルの操作を学習すると、プロジェクトを作成するときにサブファイルを 3 つの部分 (xxx.h + xxx.cpp + main.cpp) に分割できることがわかりました。

  1. ヘッダー ファイルにはクラス宣言、関数宣言、#define 定数などを記述し、通常はクラスの実装は記述しません。
  2. ソース ファイルには、cpp 記述クラスと関数の特定の実装が含まれており、通常はヘッダー ファイルに対応することが推奨されます。
  3. ソース ファイル内のもう 1 つは、定義された関数を呼び出すことができるメイン関数 main を含むファイルです。

ヘッド ファイル:

//头文件 f.h
#pragma once	//防止多次定义
#include<iostream>
using namespace std;

void demo();	//函数声明

ソースファイル:

// f.cpp
#include "f.h"

void demo()		//函数实现
{
    
    
	cout << "This is a demo" << endl;
}
//main.cpp
#include<iostream>
using namespace std;
#include "f.h"

int main() {
    
    
	demo();		//函数调用
	return 0;
}

これを見て、なぜ main.cpp にはヘッダー ファイル fh だけがインクルードされ、ソース ファイル f.cpp がインクルードされないのかという疑問が生じますこれは、関数の宣言のみを含め、関数の実装は含めないという意味ではないでしょうか? 関数宣言が含まれている場合、コンパイルを通じて main.cpp 内でそれを呼び出すことができますが、関数の実装は含まれていないため、実行時に関数の実装をどのように見つけるのでしょうか?

以下は、他の著名人からのブログ投稿や Q&A を読んで得た結論の一部です。著者自身も勉強中のため、正確でないところもあるかもしれませんが、間違いがあれば、どなたでもご指摘いただけますと幸いです。

上記の質問ですが、実際には C++ 言語の記述から実行までの一連のプロセスが含まれますが、一般的に C++ プログラムを開発するには次のような手順が必要です。

  1. コードを書いて、
  2. コンパイラがコンパイルすると、
  3. リンクするコンパイラ。
  4. 埋め込む。

関連する質問と回答で、C++ プログラム開発を飛行機の製造プロセスに例えた非常に良い回答を見つけました。詳細な回答については、https://zhidao.baidu.com/question/935481360407990892.htmlを参照してください。元の被告の答えは次のとおりです。

たとえば、飛行機を作りたい場合は、エンジン、翼、胴体、尾翼、着陸装置が必要です。これらの部品を専門のメーカーに渡して作ってもらう、これがコンパイルプロセスです。非常に多くの部品が渡されるので、それらを組み立てるだけで、これが接続プロセスです。
コンパイラ (VC など) は部品を処理するためのファクトリであり、コンパイラを通過したソース コードはオブジェクト ファイル、つまり部品になります。VC は .obj ファイルを生成します。
コネクタ (VC 下のリンクなど) は組立工場であり、すべての部品を必要なものに組み立てることができます。
さて、コンパイラとリンカーについて理解したところで、ヘッダー ファイル .h と実装ファイル .cpp の機能を見てみましょう。
さらに飛行機を例に挙げてみましょう。胴体と翼は接続されているはずですが、どのように接続されているのでしょうか?翼を作る人は翼だけを作り、胴体を作る人は胴体だけを作ります。次に、組立工場として航空機のインターフェース設計図を提供しますが、この図面には翼と胴体がどのように接続されているかが詳細に記述されていますが、翼と胴体をどのように作成するかについては記述されていません。それらの部品工場が構造図を入手した後、翼が胴体のこの部分に配置されることがわかり、それらを接続するには(たとえば)リベットを使用することが規定されていました。わかったよ。翼メーカーとして、私は胴体がどのように作られるかには興味がなく、翼の作り方と胴体とのインターフェースだけを気にします。C++ に切り替えると、インターフェイスを記述するために使用される設計図は、ヘッダー ファイルである .h ファイルです。特定のウィングの実装は、.cpp ファイルと同等です。
したがって、プログラム内で使用する必要があるのはヘッダー ファイルだけです。つまり、インターフェースの設計図だけを知っていれば十分です。インターフェース設計図に従って部品を設計したら、それを組立工場に引き渡すと、組立工場(つまりコネクタ)がすべての部品(.cppをコンパイラでコンパイルして生成された.obj)を接続してくれるので、飛行機が空に飛べるということ。

C++ プログラムの作成からコンパイル、リンク、実行までのプロセス全体を理解すると、この問題を検討するのがはるかに簡単になります。まず練習して、main.cpp の include "fh" を "f.cpp" をインクルードするように変更し、実行して、何が起こるか見てみましょう。

#include<iostream>
using namespace std;
#include "f.cpp"

int main() {
    
    
	demo();
	return 0;
}

プログラムはエラーを報告し、関数 demo() が再定義されます。
ここに画像の説明を挿入
そこで問題は、f.cpp ファイルを一度だけインクルードしたのに、なぜ繰り返し定義が表示されるのかということです。

エラーメッセージをよく観察すると、リンク期間中にエラーが発生していることがわかり、多くの人がここで問題を認識しているはずです。コンパイル時に、main.cpp ファイルと f.cpp ファイルの両方がコンパイルされて、リターゲット可能なオブジェクト ファイル (main.obj と f.obj) が生成されます。リンク時には、これら 2 つのファイルがリンカーによって自動的にリンクされます。この時、main.cppファイルにf.cppファイルをインクルードし、コンパイル時にf.cppファイルの内容に置き換え、Comeのリンク時に再度その内容を追加するという問題が出てきました。これにより、f.cpp ファイル内のデモ関数が 2 回定義されることになり、リンク エラーが報告されましたが、コンパイルではエラーが報告されませんでした。

これは実際には、コンパイル、リンク、実行プロセス全体を定義した VS2019 の強力な IDE によって引き起こされます。デバッグ ボタンをクリックするだけで、VS2019 がこれらの操作を自動的に完了します。ただし、VS2019 はコンパイル時にプロジェクト全体のソース ファイルを同時にコンパイルおよびリンクするため、これによって問題も発生しました。これまでのところ、以前に提起した問題は解決されました。main.cpp には、関数の実装ファイル f.cpp をインクルードする必要はありません。リンカーは、リンク段階で 2 つのファイルの内容を自動的にリンクします。 main関数がdemo()関数の実装を見つけることができること。実際、コンパイラはメイン関数ソース ファイルと関数実装ソース ファイルを同時にコンパイルおよびリンクし、最終的な実行可能ファイル .exe に関数実装を追加します。

つまり、fh ファイルがなく、f.cpp ファイルがインクルードされていない場合でも、main.cpp に関数宣言を手動で追加するだけでコンパイルでき、同様の結果が得られます。

//f.cpp
#include<iostream>
using namespace std;
void demo()
{
    
    
	cout << "This is a demo" << endl;
}
//main.cpp
#include<iostream>
using namespace std;
void demo();

int main() {
    
    
	demo();
	return 0;
}

操作の成功:
ここに画像の説明を挿入
.cpp ファイルをインクルードしたいだけの場合はどうすればよいでしょうか? これは実際に可能で、プロジェクト ソース ファイル内の関数の実装ファイルを右クリックし、[プロジェクトから除外] を選択して .cpp ファイルを直接含めます。

別の方法では、g++ を介してコンパイルおよびリンクするソース ファイルを指定し、main.cpp ファイルのみをコンパイルおよびリンクし、実行結果を取得することもできます。
ここに画像の説明を挿入
g++ を使用すると、前の問題が直感的にわかります。main.cpp をコンパイルして実行するだけで結果が得られますが、main.cpp と f.cpp の 2 つのファイルを同時にコンパイルしてリンクすると、エラーが報告され、デモが行われます。 () は再定義されます。(VS2019で報告されたエラーと一致します)

これらの方法は、.cpp ファイルを含めることも可能であることを示しているだけですが、実際の操作プロセスではそうすることはお勧めできません。プロジェクトファイルの数が多い場合、各種ファイルのインクルード操作により再定義が容易に発生します。関数の宣言は繰り返すことができ、それをヘッダー ファイルに置くだけで、他のソース ファイルへのインターフェイスを提供し、再定義の問題を回避できます(ヘッダー ファイルに構造体などの宣言が含まれている場合は、#pragma Once または #ifndef...#define...#endif を使用して再定義を回避することもできます)

おすすめ

転載: blog.csdn.net/lyb06/article/details/127501959