C ++でプロジェクトを作成する場合、ファイルセグメンテーション管理が非常に必要です。今日、Foxin Technology Channelの編集者は、C ++のヘッダーファイルとソースファイルの詳細な説明をお届けします。この知識を学ぶことが役立つことを願っています!
C ++のヘッダーファイルとソースファイルの詳細な説明
1。C++コンパイルモード
一般に、C ++プログラムには、.cppファイルと.hファイルの2種類のファイルのみがあります。その中で、.cppファイルはC ++ソースファイルと呼ばれ、C ++のソースコードが配置されます。 .hファイルはC ++ヘッダーファイルと呼ばれ、C ++のソースコードが配置されます。
C ++言語は「個別のコンピレーション」をサポートしています。言い換えれば、プログラムのすべての内容は異なる部分に分割し、異なる.cppファイルに配置できます。 .cppファイルのものは比較的独立しています。コンパイル(コンパイル)の場合、他のファイルと通信する必要はありません。ターゲットファイルにコンパイルした後、他のターゲットファイルとのみリンクする必要があります。たとえば、グローバル関数「void a(){}」はファイルa.cppで定義されており、この関数はファイルb.cppで呼び出す必要があります。それでも、ファイルA.CPPとB.CPPは、お互いの存在を知る必要はありませんが、個別にコンパイルすることができます。それらをターゲットファイルにコンパイルした後、リンクすると、プログラム全体を実行できます。
これはどのように達成されますか?執筆プログラムの観点から見ると、非常に簡単です。 file b.cppで、「void a()」関数を呼び出す前に、関数「void a();」を宣言します。初め。これは、コンパイラがb.cppをコンパイルするときにシンボルテーブルを生成するためです。見られない「void a()」のようなシンボルは、このテーブルに保存されます。もう一度リンクすると、コンパイラは他のオブジェクトファイルでこのシンボルの定義を探します。見つかったら、プログラムをスムーズに生成できます。
ここに言及されている2つの概念があり、1つは「定義」であり、もう1つは「宣言」であることに注意してください。簡単に言えば、「定義」とは、シンボルを完全かつ完全な方法で記述することを意味します。変数であろうと関数であろうと、どのタイプであるか、必要なパラメーターなどを意味します。「宣言」は、このシンボルの存在を宣言するだけです。つまり、このシンボルが他のファイルで定義されていることをコンパイラに伝えます。最初に使用します。リンクするときは、別の場所に行ってそれが何であるかを見つけてください。定義するときは、C ++構文に従って記号(変数または関数)を完全に定義する必要があり、宣言する場合は、このシンボルのプロトタイプを書くだけです。シンボルはプログラム全体で複数回宣言できるが、一度だけ定義する必要があることに注意する必要があります。シンボルの2つの異なる定義がある場合、コンパイラが誰を聞くべきかを想像してください。
このメカニズムは、C ++プログラマーに多くの利点をもたらし、プログラムを作成する方法にもつながります。プログラム全体の多くの.cppファイルで呼び出される非常に一般的に使用される関数「void f(){}」がある場合、この関数を1つのファイルに定義し、他のファイルでこの関数を宣言する必要があることを考えてください。関数は簡単に対処でき、それを宣言するための1つの文だけを意味します。ただし、数学的な関数の束など、機能が多すぎたら、何百もの機能がありますか?すべてのプログラマーは、すべての機能をそれらの形で正確に書き留めて書き留めることができますか?
2。ヘッダーファイルとは何ですか
明らかに、答えは不可能です。しかし、プログラマーが非常に多くの関数プロトタイプを覚えておくというトラブルを救うのに役立つ非常に簡単な方法があります。最初に何百もの機能のすべての宣言ステートメントを書いて、それらをファイルに入れることができます。プログラマーがそれらを必要とする場合は、これらすべてをソースコードにコピーします。
この方法は確かに実現可能ですが、それでも面倒すぎて不器用に思えます。そのため、ヘッダーファイルがその役割を果たすことができます。いわゆるヘッダーファイルは、実際には.cppファイルのコンテンツと同じコンテンツを持ち、どちらもC ++ソースコードです。ただし、ヘッダーファイルをコンパイルする必要はありません。すべての関数宣言をヘッダーファイルに入れます。 .cppソースファイルが必要な場合、マクロコマンド「#include」を介してこの.cppファイルに含めることができ、そのコンテンツが.cppファイルにマージされます。 .cppファイルがコンパイルされると、これらの含まれた.hファイルの関数が再生されます。
例を挙げましょう。すべての数学関数には2つしかないと仮定します。F1とF2は、それらの定義をmath.cppに入れます。
/ * math.cpp */double f1(){//ここで何かをする... return;} double f2(double a){//ここで何かをする... a * a;}/ * end of math.cpp */そして、ヘッダーファイルMath.hに「Theme Theming」関数の宣言を入れます:
/ * math.h */double f1(); double f2(double);/ * end of math.h */
別のファイルmain.cppでは、これら2つの関数を呼び出したいので、ヘッダーファイルを含める必要があります。
/ * main.cpp */#include "math.h" main(){int number1 = f1(); int number2 = f2(number1);}/ * main.cppの終わり */これは完全なプログラムです。 .hファイルはコンパイラのコマンドの後に記述する必要はないが、コンパイラがそれを見つけることができる場所(たとえば、main.cppと同じディレクトリ)で見つける必要があることに注意する必要があります。 main.cppとmath.cppをコンパイルしてmain.oとmath.oをそれぞれ生成し、これらの2つのオブジェクトファイルをリンクすると、プログラムを実行できます。
3。#include
#includeは、コンパイラがコンパイルする前、つまり事前コンパイルされたときに動作するC言語のマクロコマンドです。 #includeの目的は、その後に記述されたファイルのコンテンツを現在のファイルに完全かつ完全に含めることです。他の機能やサブ機能がないことに言及する価値があります。その機能は、表示されるすべての場所を、その背後に書くファイルのコンテンツに置き換えることです。単純なテキストの交換、他に何もありません。したがって、main.cppファイル(#include "math.h")の最初の文は、コンパイル前にmath.hファイルの内容に置き換えられます。つまり、編集プロセスが開始されると、main.cppのコンテンツが変更されました。
/ * 〜main.cpp */double f1(); double f2(double); main(){int number1 = f1(); int number2 = f2(number1);}/ * 〜main.cpp */ */ *それ以上のことはありません、ちょうどいいです。同様に、Main.cppに加えてF1およびF2関数を使用する場合、これら2つの関数を使用する前に#include "math.h"を文字で記述する必要があります。
4。ヘッダーファイルに何を書くべきか
上記の議論を通じて、ヘッダーファイルの機能が他の.cppに含まれることを理解できます。彼ら自身はコンピレーションに参加していませんが、実際、その内容は複数の.cppファイルにまとめられています。 「定義は1回だけ」のルールを通じて、変数と関数宣言のみをヘッダーファイルに配置する必要があり、それらの定義を配置しないでくださいと簡単に結論付けることができます。ヘッダーファイルの内容は実際には複数の異なる.cppファイルに導入され、すべてコンパイルされるためです。もちろん、宣言をしても大丈夫です。定義を配置すると、複数のファイルに表示されるシンボル(変数または関数)の定義と同等です。これらの定義は同じですが、コンパイラがそうすることは合法ではありません。
したがって、覚えておくべきことの1つは、.hヘッダーファイルには、変数または関数宣言のみが存在することができ、定義を配置できないことです。つまり、次のような文です。およびvoid f();ヘッダーファイルでのみ記述できます。これらは声明です。 int aのような文を書く場合。またはvoid f(){}、その後、ヘッダーファイルが2つ以上の.cppファイルに含まれると、コンパイラはすぐにエラーを報告します。 (外部について、それは以前に議論されており、定義と宣言の違いはここでは議論されません。)ただし、この規則には3つの例外があります。
1. constオブジェクトの定義は、ヘッダーファイルに記述できます。グローバルconstオブジェクトはデフォルトではexternによって宣言されていないため、現在のファイルでのみ有効です。そのようなオブジェクトをヘッダーファイルに書き込みます。他の複数の.cppファイルに含まれている場合でも、オブジェクトはファイルを含むファイルでのみ有効であり、他のファイルには見えないため、複数の定義にはつながりません。同時に、これらの.cppファイルのオブジェクトはヘッダーファイルから含まれているため、これらの.cppファイルのconstオブジェクトの値が同じであることが保証されます。同様に、静的オブジェクトの定義をヘッダーファイルに配置することもできます。
2。インライン関数の定義は、ヘッダーファイルに記述できます。インライン関数は、コンパイラが最初に宣言してからリンクされる(インライン関数がリンクされない)単なる通常の関数ではなく、それが遭遇する場所の定義に従ってインラインする必要があるため、コンパイラはコンパイル中のインライン関数の完全な定義を確認する必要があります。インライン関数を通常の関数のように一度しか定義できない場合、これを行うのは困難です。ファイルでは問題ないため、最初にインライン関数の定義を書くことができます。そのため、後で使用すると定義を確認できます。しかし、他のファイルでこの関数を使用した場合はどうなりますか?これに対する良い解決策はほとんどないため、C ++は、インライン関数をプログラムで複数回定義できると規定しています。インライン関数が.cppファイルに1回のみ表示される限り、すべての.cppファイルで、このインライン関数の定義は同じであり、コンパイルできます。その後、明らかに、インライン関数の定義をヘッダーファイルに配置することは非常に賢明です。
3.クラスの定義は、ヘッダーファイルに記述できます。プログラム内でクラスオブジェクトを作成する場合、コンパイラはこのクラスの定義が完全に表示されている場合にこのクラスのオブジェクトをどのようにレイアウトするかを知ることができるため、クラスの定義の要件は基本的にインライン関数と同じです。したがって、クラス定義をヘッダーファイルに入れて、このクラスで使用されている.cppファイルにヘッダーファイルを含めることをお勧めします。ここでは、クラスの定義にデータメンバーと関数メンバーが含まれていることに言及する価値があります。データメンバーは、特定のオブジェクトが作成されるまで定義されません(割り当てられたスペース)が、関数メンバーは最初から定義する必要があります。これは通常、クラスの実装と呼ばれるものです。一般的に、私たちのアプローチは、クラス定義をヘッダーファイルに配置し、関数メンバーの実装コードを.cppファイルに配置することです。これは大丈夫で良い方法です。ただし、別の方法があります。つまり、機能メンバーの実装コードをクラス定義に直接書き込むことです。 C ++クラスでは、関数メンバーがクラス定義本体で定義されている場合、コンパイラは関数をインラインと見なします。したがって、関数メンバーの定義をクラス定義本体に書き込み、ヘッダーファイルにまとめることは合法です。クラス定義のヘッダーファイルに関数メンバーの定義を書くことは違法であり、クラス定義には含まれていないことに注意してください。この時点で関数メンバーはインラインではないためです。ヘッダーファイルが2つ以上の.cppファイルに含まれると、この関数メンバーが再定義されます。
5。ヘッダーファイルの保護対策
ヘッダーファイルに宣言ステートメントのみが含まれている場合、同じ.cppファイルに何度も含まれている場合は問題ありません。宣言ステートメントの発生は無制限であるためです。ただし、上記のヘッダーファイルの3つの例外も、ヘッダーファイルの非常に一般的な使用です。その後、上記の3つの例外のいずれかがヘッダーファイルに表示され、.cppが複数回含めると、問題は大きくなります。これらの3つの例外の構文要素は「複数のソースファイルで定義できる」が、「1つのソースファイルに1回のみ表示できる」ためです。 AHにクラスAの定義が含まれており、BHにクラスBの定義が含まれている場合、クラスBの定義はクラスAに依存するため、AHはBHにも#includedです。これで、クラスAとクラスBの両方を使用するソースファイルがあるため、プログラマーにはこのソースファイルにAHとBHの両方が含まれています。この時点で、問題が発生します。クラスAの定義は、このソースファイルに2回表示されます!そのため、プログラム全体をコンパイルできません。あなたはそれがプログラマーの間違いだったと思うかもしれません - 彼はBHにAHが含まれていることを知っているべきです - しかし、彼はそうすべきではありません。
条件付きコンピレーションで「#define」を使用すると、この問題をうまく解決できます。ヘッダーファイルでは、#defineを介して名前が定義され、#ifndef ...#endifは条件付きでコンパイルされているため、コンパイラが名前が定義されているかどうかに基づいてヘッダー内の後続コンテンツをコンパイルし続けるかどうかを決定できます。この方法は簡単ですが、ヘッダーファイルを書くときに書くことを忘れないでください。
この記事を読んでいただきありがとうございます。この記事で紹介されたC ++のヘッダーファイルとソースファイルの詳細な説明が役立つことを願っています。 New Technology Channel Networkからサポートしていただきありがとうございます!