詳細C ++ヘッダファイルとソースファイル内の役割

、C ++コンパイラモード

.cppファイルと.hファイル - ファイルの2種類のみが含まれている一般的には、C ++プログラム。ここで、ファイルの.cpp C ++ソースファイルはC ++ソースコードに入れている、と呼ばれ、.hファイルはC ++ソースコードに入れてC ++ヘッダファイルと呼ばれました。

C ++言語サポート(separatecompilation) "をコンパイルしています"。つまり、番組の内容の全てが異なるセクションに分割することができ、異なる.cppファイルに入れました。物事は比較的独立している.cppファイルは、コンパイルの時間(コンパイル)で、他の文書と通信する必要はありません、あなただけが他のオブジェクトファイルとオブジェクトファイルにコンパイルして、行にリンク(リンク)を行うことが必要です。例えば、ドキュメントには、グローバルa.cpp関数で定義され、ファイルb.cppこの関数を呼び出す必要があり、「(){}は無効」。そうであっても、a.cpp b.cppファイルやドキュメントは、互いの存在を知っている必要はありませんが、それらは別々にコンパイルして、全体のプログラムを実行することができた後、リンクされたオブジェクトファイルにコンパイルすることができます。

これは、それを達成する方法ですか?懸念しているプログラムの観点から書かれた、それは非常に簡単です。ファイル内B.cpp、機能についての最初の文の前の機能「()無効」に呼び出し、その上で、「voidaを()」。これは、コンパイル時のb.cppで、コンパイラがシンボルテーブル(シンボルテーブル)を生成しているためで、「無効()」のシンボルのような定義を見ていない、このテーブルに格納されます。ときに別のリンク、コンパイラは、このシンボルの定義を見つけるために、別のオブジェクトファイルになります。見つけたら、プログラムが正常に生成されます。

二つの概念の言及に注意し、1は「定義」で、「声明」です。簡単に言えば、「定義は」完成作品を記述するためのシンボルである:それは変数であるか、どのようなパラメータがそうで必要とどのようなタイプを返す関数。あなたが何であるかを確認するために、最後にそれを見つけるために他の場所を試してみリンクする際に「文」は、私と一緒に最初に、このシンボルが別のファイルで定義されているコンパイラに指示します。このシンボルの存在の単なる文ですそれは。定義された時間Yaoan C ++構文を完全シンボル(変数や関数)を定義し、それが唯一の宣言されたときには、このシンボルのプロトタイプを記述する必要があります。なお、シンボルは、プログラム全体では何度も宣言することができますが、一度だけ定義し、する必要があります。シンボルは、2つの異なる定義に耳を傾けるようにコンパイラに表示された場合だけ、と思いますか?

また、多くのメリットをもたらしますが、C ++プログラマのためのこのメカニズムは、書き込みプログラムの方法につながります。プログラム全体の多くの.cppファイルの「無効F(){}」は、呼び出されることは非常に便利な機能がある場合、他にいる間、我々は唯一、ファイルにこの関数を定義する必要があり、考えてみましょう文書はそれにその関数を宣言しました。幸いなことに対処するための機能が、それは言葉を宣言します。多くの数学関数の多くのような関数場合は、何百もある、そしてどのように行うの?すべてのプログラマが完全に正確に書き留めているすべてのフォーム機能を入れて書き出すことができますようにするには?

第二に、最初の文書は何ですか

もちろん、答えは不可能です。しかし、非常に単純な方法があり、プログラマはそんなにトラブルの関数プロトタイプを覚えておく必要がなくなり助けることができます。私たちは機能の何百ものすべての最初のファイルには、プログラマがするまで待つ必要があり、書かれているという声明を宣言することができます自分の時間は、ソースコードの彼のコピーに、これらすべてのものを入れます。

このアプローチは確かに実現可能な、まだあまりにも面倒でなく、不器用です。このように、ヘッダはにおけるその役割を再生できるようになります。いわゆるヘッダファイルは、実際には、.cppファイルとそのコンテンツの内容が同じである、C ++ソースコードです。しかしなしヘッダファイルがコンパイルされています。我々は、すべてのヘッダファイルにすべての関数宣言を入れ、1の.cppソースファイルがそれらを必要とするとき、それらは、マクロコマンドを通じて「の#include」することにより、その内容をマージし、この.cppファイルに含めることができますファイルを.CPPします。.cppファイルは、これらの.hファイルの役割に含まれるように、コンパイルされたときに再生されます。

その後、我々はmath.cppで定義に入れ、f1とf2:例として、すべての数学関数は2つだけであることを前提としています。

/ * math.cpp * / 
ダブルF1()
{ 
// ...ここに何かを
返します。
} 
ダブルF2(ダブルA)
{ 
//ここに何かを... 
* aを返します。
} 
/ * math.cppの終わり* /

そして文は、「これら」の機能は、ヘッダファイルmath.hに配置されています。

/ *のmath.h * / 
ダブルF1(); 
ダブルF2(ダブル); 
/ *のmath.hの終わり* /

別のファイルmain.cppには、私は、あなただけ含まれているヘッダファイルに来る必要があり、この2つの関数を呼び出したいです:

/ * main.cppに* / 
の#include "のmath.h" 
のmain()
{ 
int型数値1 = F1()。
int型数値2 = F2(数値1)。
} 
/ * main.cppにの終わり* /

このように、それは完全な手順です。なお、.hファイルには、コンパイラのコマンドの後に書いていないが、それはmain.cppにとmath.cppは別途を通じて利用可能です(そのようなディレクトリでmain.cppを持つように)コンパイラを見つけるための場所でなければなりません、コンパイルmain.oとmath.o、その後、2つのオブジェクトファイルをリンク、プログラムが実行することができます。

三、#は、

それは、プリコンパイル時に戦場に出たコンパイラでコンパイルされる前の#includeは、C言語からのマクロコマンドです。#INCLUDE役割は、その背後に書かれた内容を文書化することです、完成作品は、単語のための単語は過去に、現在のファイルに含まれています。その役割は、その背後に書かれたそのファイルの内容を置き換え、それが表示されるすべての場所にあり、それ自体が悪徳の他の役割と機能はないということである言及する価値があります。単純なテキスト置換、何もありません。そのため、内容をコンパイルする前に、最初の文(の#include「のmath.h」)main.cppにファイルは、ファイルのmath.hを置き換えられます。コンパイル処理が開始された場合にはmain.cppに内容が変更されている、次のとおりです。

/ *〜* main.cppに/ 
ダブルF1(); 
ダブルF2(ダブル); 
メイン()
{ 
int型数値1 = F1()。
int型数値2 = F2(数値1)。
} 
/ *〜main.cppにの終わり* /

過言ではない、ちょうどいい。我々はmain.cppを除いて、他の多くの.cppファイルも使用関数f1とf2がある場合、同じが、見ることができ、それらすべては、ちょうどこの2つの関数を使用する前の#include」数学を記述する必要があります。ライン上の時間」。

第四に、ヘッダファイルには何を書くべき

上記の議論では、我々は、ヘッダファイルの役割は、他の.cppファイルに含まれている理解することができます。彼らは、自身が関与していないコンパイラ、実際には、それらの内容は、複数の.cppファイルにコンパイルされています。「一度だけ定義される」ルールによって、我々は簡単に、描画ヘッダファイルのみを変数と関数を宣言する必要があります置くが、その定義を置くことができないことができます。ヘッダファイルの内容が実際に異なる.cppファイルの数に導入され、それらがコンパイルされますので。もちろん、あなたが定義を置けば右に置くステートメントが、シンボル(変数や関数)の定義に複数のファイルに表示されるように相当し、これらの定義は同じであっても、しかし、コンパイラのためにそうします違法。

したがって、我々は.Hヘッダファイルには、変数を宣言または関数が唯一存在することができますが、定義を入れていないこと、心に留めておく必要があります。)(ボイドF;のextern INT文:すなわち、フォームのみヘッダファイルに記述することが可能です。これらは、文です。書き込みINTA場合、または空隙Fが(){}このような文章、これは、2つ以上のファイル.cppファイルの最初に一旦直ちに、コンパイラエラーが含まれていました。(EXTERNについて、私たちは前に説明してきた、文の定義との違いを議論はもはやありません。)

しかし、このルールは3つの例外があります:

  • まず、ヘッダファイルの定義は、constオブジェクトを書き込むことができます。グローバルなデフォルトにはにextern constのオブジェクトが宣言されていないので、現在のファイルでのみ有効ですので。このようなオブジェクトは、それが他の.cppファイルの数が含まれている場合でも、ヘッダファイルに書き込まれ、このオブジェクトは唯一、それが有効なドキュメントが含まれていることでもあり、他のファイルは表示されませんので、彼らはしませんこれは、複数の定義につながります。同時に、これらの.cppファイルはconstオブジェクトのこれらの.cppファイルの値は同じ意味であることを保証するヘッダファイルからオブジェクトに含まれているからです。同様に、静的オブジェクトの定義は、ヘッダファイルに配置することができます。

  • 第二に、ファイルヘッダは、インライン関数の定義(インライン)A書き込むことができます。コンパイラはその定義それインライン展開に応じてではなく、通常の関数として検出した場合にインライン関数が必要とされるため、コンパイラはする必要があるので、(インライン関数がリンクされていない)、再リンク宣言することができコンパイル時にインライン関数ジョブの完全な定義を参照してください。通常の関数のようなインライン関数は一度だけ定義することができた場合は、この事は簡単なもの。幸いにも、あなたは時間の使用が定義の後ろに見ることができることを確認できるように、ファイルには、私は、初めに書かれたインライン関数を定義することができますので、しかし、私はどのようにすることを他のドキュメントでこの機能を使用する必要がある場合それを行うには?、.cppファイルで、このインラインこれはほとんど良い解決策ではありません、そのため、インライン関数は、インライン関数として何度でもプログラムでC ++の規定を定義することができ、一度だけ表示され、すべての.cppファイルに定義された関数が同じで、コンパイルすることができるようになります。だから、明らかに、ヘッダファイルにインライン関数の定義は非常に賢明です。

  • 第三に、ヘッダファイルの定義を書き込むことができクラス(クラス)があります。あなたはレイアウトべきか、このクラスのオブジェクトに知るためには、唯一の完全に見えるのクラスの定義場合は、プログラムの中でコンパイラをクラスのオブジェクトを作成するときので、そのクラス定義のための要件、インライン関数が基本であると同じ。だから、ヘッダファイルにクラス定義は、このヘッダファイルを含めるには、このクラスの.cppファイルを使用し、それは良い習慣です。ここでは、クラス定義は、データメンバーとファンクションメンバーが含まれていることを言及する価値があります。データメンバーが作成された場合に、特定のオブジェクトが(割り当てられた領域)を定義することになるまで待つことであるが、それはメンバーの関数である冒頭に定義する必要があり、これは、我々は通常クラスを参照達成されます。一般的に、我々のアプローチは、そのヘッダファイルでクラス定義、および.cppファイル内の関数メンバの実装コードです。それは可能であり、それは良い解決策です。しかし、別の方法があります。これは、実装コードのメンバーの直接の機能はまた、クラス定義内に記述されています。関数は、クラスの本体部材の定義で定義されている場合、C ++クラスでは、コンパイラは、インライン関数を表示します。そのため、クラス定義の定義は、関数メンバの本体に書き込まれ、ヘッダファイルをまとめ、合法です。ヘッダーファイルでクラス定義で記述された定義された関数のメンバー場合、なお、この時点で、この関数がインラインのメンバーではないため、違法であるクラス定義に書き込まれません。ヘッダが2であるか、.cppファイルが含まれていたら、この関数のメンバーが再定義されました。

第五に、ヘッダファイルの保護対策

なぜなら出現宣言文の無制限です - のみ宣言を含むヘッダファイルは、それが同じ再び何度も何の問題が含まれている.cppファイルがある場合は、考えてみましょう。しかし、ヘッダファイル内の3つの例外を除き、上述のヘッダファイルは、非常に一般的な使用です。ヘッダファイルは、上記の3つの例外のいずれかに表示されたら次に、それは、複数の単語を含んで、問題が大きい再びの.cppました。「複数のソースファイルで定義することができ、」けれども、これらの3つの例外の構文要素ので、しかし、「唯一のソースファイルに一度表示されます。」クラスAの定義は、依存クラスBの定義から、クラスBで定義された含有BH、ああ含まれている場合、想像し、そうする#includeもBHああ。今では、両方のソースファイルは、ああ来含まへのクラスAとクラスB、その後、プログラマを使用して、BHも来て含まれ、ソースがあります。この時点で、質問が来た:クラスAの定義は、ソース・ファイルに二回表示されます!だから、全体のプログラムはコンパイルされません。あなたは、これはプログラマの間違いだと思うかもしれない - 彼はBHがああが含まれている知っている必要があります - しかし、実際には彼が知っているべきではありません。

この問題を解決することができます条件付きコンパイルで「の#define」を使用してください。コンパイラがかどうかを名前で定義して、ヘッダファイルの内容をコンパイルし、その後に継続するかどうかを決定することができるように#define名によって定義されたヘッダファイルでは、条件付きコンパイル通じ#ifndefの...#endifの。この方法はシンプルですが、私たちは、書き込みヘッダファイルへの書き込みを覚えておく必要があります。

C ++ヘッダファイルとソースファイルとの間の差

まず、ソースファイルを関連付ける方法に応じての#includeヘッダ

1は、システムは、角括弧内のファイル・ヘッダーが付属し、コンパイラは、ファイル・システム・ディレクトリになります。

2、ファイルのユーザ定義囲まれた、コンパイラはまずVCなどの(C ++インストールディレクトリに、ユーザディレクトリ内の二重引用符を見て、となり、環境変数を通じて、UnixおよびLinuxをライブラリ検索パスを指定して変更することができます)を設定、およびファイルシステムの最後の表情。
#include「xxx.h」(私はいつも「と思った」と<>違いはありませんが、非システム内のすべてのファイルtinyxml.h、その使用「」)

第二に、どのようにソースファイルのヘッダを関連付けます

これらの機能を達成するための質問本当に、「ああ」ヘッダファイルに知られている機能のセットを宣言し、「b.cpp」、私は「ああ」「c.cpp」これらの中で宣言を使用したいので、もし通常は「c.cpp」に「ああ」の#includeを使用している「b.cpp」で実現される機能、それに見つけるb.cpp達成するためにどのようにc.cpp?

実際には、.cppファイルと.hファイル名は任意の直接的な関係を持っていない、多くのコンパイラは、他の拡張機能を受け入れることができます。たとえば、今もの.ccファイルに置き換えクラッシュ、同社のソースコード、.cppファイルを参照してください。

ターボC、ファイルの名前のためのコマンドライン引数をコンパイルするためのコマンドラインを使用することで、デフォルトでは、.cppファイルと.hのですが、またように.XXXとするためにカスタマイズすることができます。

「Cプログラミング」事前コンパイラは、「ファイル処理を含む」のコマンドを#includeするため、書籍のハオ強い先生は:「file2.c」場所を#includeするfile2.cの内容全体をコピーします。#include前処理は、「コピーをして、コードの挿入」完成作業をすることであるため、多くのコンパイラが----ファイルの拡張子が何であるかを最終的には気にしない理由も説明しています。

時間をコンパイルし、そしてこの作品のみリンク時に行われ、機能b.cppファイルを実現するために行くことはありません。私たちは、実装がある場合、コンパイラは、それが達成する方法で、気にしないことができるように、実際に文の導入に関連して、「ああ」の#includeでb.cppまたはc.cpp。ソースファイルはオブジェクトファイルグリーン(・Oまたは.OBJファイル)ターゲット・ファイルにコンパイルされた後に、これらの関数および変数は、シンボルとして扱わ。説明または.oのファイルを.OBJする必要があるリンクは、(ここでb.cpp .objファイル生成または.oのファイル)の内部メイクファイルに接続しなければならない場合は、この時間は、コネクタにファイルまたは.objファイルをの.oますでb.cppで実現される機能を見つけ、その後、実行可能ファイルを指定することができますメイクファイルにそれらを構築します。

Unixでは、でも、ソースファイルはメイクファイルにすることができますという名前のヘッダファイルが含まれていない(しかし、これは非常に、プログラムの可読性を低減^ _ ^ああ悪い癖です)。VCでは、独自のメイクファイルを記述する必要のないギャングは、唯一のプロジェクトに含まれている必要なファイルする必要があり、VCは自動的にメイクファイルを作成するのに役立ちます。

通常、各の.oまたは.OBJファイルにC ++コンパイラは、シンボルではなく見つけるか、のみ、特定のファイルに見つけられないために探しよりも、必要とされているものを見つけるために。同じ機能、同じではいくつかの異なるファイルに実装されたり、リンクが要求されますと、グローバル変数を定義した場合このように、「再定義」。

魅力を要約します

.hファイルを含めることができます。

  • クラスのデータメンバを宣言したが、割り当てることはできません

  • ちょうど声明のような静的なデータのクラス定義と割り当てのメンバーが、お勧めできません。

  • クラスのメンバ関数を宣言

  • 非クラスのメンバ関数の宣言

  • 定義定数:例えば:constint A = 5。

  • 静的関数を定義します

  • インライン関数の定義クラス

それは含めることはできません。

1。すべての非静的変数(データではないクラスのメンバー)宣言

2。名前空間stdを使用して、ヘッダファイル内の名前空間宣言をデフォルトしないでください。など.cppファイルに配置する必要があり、使用STDで.hファイルを::文字列

 

また、記事に興味がある可能性があります。

記事の同時リリース:  https://www.geek-share.com/detail/2769307191.html

おすすめ

転載: www.cnblogs.com/xxcn/p/10930105.html