2009-08-30 11 views
24

私はテンプレートクラスを呼び出す際に問題があります。 新しい型名Arrayを宣言しました。これはテンプレートです。C++テンプレート、リンクエラー

.HPPファイルで

:に未解決の外部シンボル:私はリンケージエラーが発生します

Array<int> arr; 

:メインで

template <typename T> 
Array<T>::Array() 
{ 
//Do something 
} 

:.cppファイルで

template <typename T> 
class Array 
{ 
public: 
    Array(); 
}; 

ctor。

+0

この質問をhttps://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-fileにリンクすると便利ですが、実際は重複していません。 OPは、その質問で完全に想定されていた何かを知らなかった。 – Winter

答えて

47

メンバ関数を含むテンプレート関数は、完全にヘッダに書き込まなければなりません。つまり、テンプレートクラスを使用している場合、その実装は完全にヘッダ内になければなりません。これは、テンプレートのインスタンス化ごとにコードを生成するために、コンパイラがテンプレート定義全体(シグネチャだけでなく)にアクセスする必要があるためです。

+0

はい、それは働いた。 ヘッダーにそのすべてを定義する必要がある理由を追加してください。加えて、私が追加した実装では、 "endif"の前にすべてを追加しました。 –

+1

正しい。理由の良い説明については、http://www.parashift.com/c++-faq-lite/templates.html#faq-35.12とmoonshadowがリンクしている次の質問35.13を参照してください。 –

+7

これは技術的には必須ではありません。いくつかのコンパイル単位でテンプレートを明示的にインスタンス化し、そのテンプレートを別の場所で使用することもできますが、手動でハウスキーピング(プロジェクトで使用される新しいタイプごとに明示的なインスタンスを追加する必要があります)まだ知られていないタイプの作業)。 –

8

テンプレートの宣言とテンプレート関数 の定義の両方をヘッダーファイルに入れます。ほとんどのC++コンパイラは、テンプレートの個別のコンパイルモデルを容易にサポートしません。

3

ここで問題があるのは、.cppファイルにコンストラクタの定義が隠されていることです。この定義はすべてタイプTに適用されます。Tintとなりますが、実際には宣言がないため、実際には何も定義されていません。
リンカはシンボルArray<int>::Array()を見つけることができません。あなたのArray.cppファイルの末尾に

Array<int> arr1; 

、これはコンパイラインスタンス化リンカが探していることを正しい定義を行います

さて、あなたはこのような行を追加することができます。しかし、これはという定義を1つだけ提供し、それはArray<int>のものです。あなたが追加する必要があり、その時点で別のテンプレートパラメータのArray、たとえば、double、必要になるまで

このソリューションは、動作します:

Array<double> arr2; 

をごArray.cppファイルの末尾にを - あなたはこれがいかにして持続不可能であるかを見ることができます!

のいずれかを扱うにはC++が必要な場合は、今後はctorの定義を(おそらくすべての他のメンバー関数を)ヘッダーに移動してください.cppファイルには何も残っていません)。

0

上記のように、C++のテンプレートでは、コンパイル時に新しいメソッドのプロセスがコンパイル時に実行されますが、問題はその時間中のthmのすべての定義を知る必要があるため、すべてのクラス/関数宣言はar hまたはhppファイル。

1

もう1つの答えは、.cppファイル(メインではない)だけをコンパイルし、オブジェクトファイルのサイズを確認してからempty.cppファイルを作成し、そのempty.cppをコンパイルします。最終的に両方のオブジェクトファイルのサイズを比較します。同じサイズであることがわかります。つまり、.cppファイルがコンパイラに何もないので、リンカは何も見つけることができません。