1

ヘッダー ファイルで定義を提供すると、他のファイルがそれらを参照できるようになり、リンカがすべてのオブジェクト ファイルをまとめて追加し、後で定義を提供することを理解しています。

これは、他のライブラリの他の場所で実装を再利用できるようにするためですか?

ヘッダー ファイルを使用せず、悪用してすべてのコードをヘッダー ファイルに入れたら、つまり完全な実装はどうなるでしょうか? 完全な定義をピア ファイルごとにコンパイルする必要があるため、各ファイルをコンパイルするときに時間がかかりますか? 同じ実装の複数のコンパイル済みバージョンになるため、リンカーで問題が発生しますか?

これはテンプレートでどのように機能しますか?

ブレア

4

3 に答える 3

2

ヘッダー ファイルに配置されたコードは、新しいコンパイル ターゲットにそのヘッダー ファイルが含まれるたびにコンパイルされるため、少なくともはい、コンパイルに時間がかかります。ただし、これは一般的に重大な問題ではありません。

このヘッダーがあるとしましょう:

int f_header() {
    return 0;
}

そして、これらのソース ファイル:

/* a.cpp */
#include "myheader.h"
int f_a() {
    return f_header();
}


/* b.cpp */
#include "myheader.h"
int f_b() {
    return f_header();
}

これらの各ソースをコンパイルすると、コンパイルは成功します。ただし、プログラムをリンクすると、関数が 2 回提供されるため、リンカは失敗しますf_header()

テンプレートは実際にはコードではないため、特殊なケースですが、さまざまなタイプに基づいてコードを生成するためのテンプレートを提供します。複数のソース ファイルが同じ型でそれらを使用する場合、重複のように見えますが、コンパイラはこの特殊なケースを処理できます。

于 2012-11-12T12:40:27.287 に答える
0

ソース ファイルとヘッダー ファイルのコードを分割することは、多かれ少なかれ歴史的に必要でした (ですか?)。これにより、コンパイラは、プロジェクト全体が大きすぎて一度にコンパイルできない場合に、大きなプロジェクトのコード単位を個別にコンパイルできるようになりました。

また、変更されていないコンパイル単位をキャッシュできるため、コンパイル時間がさらに短縮されます。

技術的には、コンパイラはさまざまなコンパイル単位のセット全体を認識します。同じ定義の複数の実装を提供する場合、コンパイラは何も教えてくれません。しかし、リンカは、コンパイルされたユニットを単一の実行可能ファイルにラップすると、それでつまずきます。

今日、C# や Java などの「最新の」言語は、この歴史的な制約から離れました。しかし、C++ はコンパイラにとっても複雑な言語であるため、これらの利点は何らかの形で依然として関連しています。

于 2012-11-12T12:39:19.520 に答える
0

コンパイラは一度に 1 つのファイルをコンパイルします。コンパイラが解析しているソース ファイルには他のファイルが含まれている場合がありますが、含まれているすべてのファイルはコンパイル前の段階で単一のソースに "フラット化" され、コンパイラは 1 つのコード エンティティを "認識" します。

上記により、コンパイラはその区別をしないため、コードが .cpp または .h ファイルにあるかどうかはコンパイラにとって重要ではありません。ただし、関数定義または変数定義が .h ファイルにある場合、リンク段階で問題が発生します。

リンカはソース ファイルを認識しませんが、コンパイラが生成する結果であるオブジェクト ファイル (.obj) を認識します。リンカーは、各オブジェクト ファイル内のすべての関数とすべての変数を認識しており、リンカーの仕事は、それらを 1 つの実行可能ファイルにまとめてバインド (またはリンク) することです。異なるオブジェクト ファイルに同じ名前の変数または関数が複数ある場合、リンカはそれらの処理方法を失い、エラーを宣言します。すべての余分な変数と関数を無視するオプションをリンカーに強制することは可能ですが、そのオプションは安易に使用しないでください。同じ名前の 2 つの関数は、実際には完全に異なる場合があり、そのうちの 1 つを無視すると、あらゆる種類のエラーが発生します。

一方、テンプレートは関数ではありません。これらは実際の機能の設計図です。コンパイラがテンプレートに遭遇しても、実質的なことは何も起こりません。テンプレートが実際の関数にインスタンス化された場合にのみ、コンパイラはそのような関数を作成します。このため、テンプレートはヘッダー ファイルに問題なく配置できます。

于 2012-11-12T12:45:18.170 に答える