2009-03-13 20 views
15

私は本当に理解していない問題があります。クラスNodeを持っています。テンプレート付きのC++クラスでコンストラクタが見つかりません

template<class T> 
class node { 
protected: 
    T _data; 
public: 
    node(T data); 
}; 

これは "node.h"ファイルにあります。 "node.cpp" ファイルでは、このコンストラクタがあります:

#include "node.h" 

template<class T> 
node<T>::node (T data) { 
    _data = data; 
} 

コンパイラがエラーを発見しませんが、リンカ(ld)が私に語った:

は/ usr/binに/ LD:未定義のシンボル:

ノード< int型> ::ノード(int型)

変な部分...コンストラクタを.cppから.hファイルに移動すると、すべて正常に動作します。問題はどこだ?

答えて

23

テンプレートはクラスではなく、通常は2つの別々のファイルに書き込まれません。テンプレートクラスは、コンパイラがに生成するコードで、クラスを生成します。そのため、実装コードは、インラインで、つまり発見したヘッダーにインラインである必要があります。

の詳細については、の理由があります。C++ FAQ Liteを参照してください。

13

一般に、すべてのテンプレートメンバーをヘッダーファイルの内側に配置する必要があります。テンプレートは、使用されたベースでコンパイルされるため、定義全体が使用されている場合はいつでも使用可能にする必要があります。コードをヘッダファイルに置くと、その問題が解決されます。

テンプレート定義をCPPファイルに入れることができるのは、テンプレートがそのCPPファイル内でのみ使用される場合だけです。その理由は、定義全体がコンパイルに使用できるという基準を満たしているからです。

node.cppの内容をnode.hに移動すると、問題が解決されます。

奇妙なシナリオ

その後、再び、あなたはまた、CPPファイルにすべてをかけるとCPPファイルを含めることができます。 C++はこのように柔軟性があります。私はこれまで言及してきたので、私はこれを言います。私の顎が私の机の上に当たったとき、私は実際に傷つきました。

+1

を使用プライベートである必要がありますが、そうである必要はありません)。 – rmeador

1

node<int>を使用すると、おそらくnode.cppは含まれていません。したがって、コンパイラはnode<int>::node<int>コンストラクタをインスタンス化できません。通常は、メソッドのすべての実装を含むすべてのテンプレートコードをヘッダーファイルなどに入れます。

0

関数への呼び出しがない限り、コンパイラはコードを出力せず、リンカーはそれを見つけられません。

関数は、その関数が属するヘッダーに配置する必要があります。

+0

私はまだそれを取得しません。テンプレートが別のヘッダとソースコードを持つクラスでないのはなぜですか? 自分のリストを書いてみましょう ..すべてのリストメソッドをヘッダファイルに含める必要がありますか? –

+0

はい、これが最も一般的な方法です。 List.hの一番下に#include "List.cpp"することもできます。 –

+0

ok。私はヘッダーファイルにすべてを含めることが奇妙であることを発見しました。実際のコードは質問の数行より少し長いです(バイナリ検索ツリーです)。 –

0

暗黙のインスタンス生成をオフにし、あなたのコード内

template class node<int>; 

どこか(多分node.cpp)

EDIT必要があります:悪い答えを、それはおそらくそうではないのです。

+1

これは悪い答えだと思うなら、それを削除してからdownvotedすることができます。 –

1

一般的に受け入れられている方法は、すべての実装を.hファイルに入れて、必要に応じてテンプレートからクラスを生成できるようにすることです。

テンプレートのインスタンス化先のタイプがわかっている場合は、少しでも不正行為をする可能性があります。 .cppに必要なタイプとメソッドのユースケースが含まれていることを確認してください。ユースケースはテンプレートコードの後に​​来ることが重要です。例えば。 「node.cpp」のために、あなたはそう、彼らは、これを強制(他の場所でそれらを呼び出すするつもりはありませんしている場合にもCPPファイルに非テンプレート化クラスのテンプレート化メンバ関数を置くことができます

#include "node.h" 

template<class T> 
node<T>::node (T data) { 
    _data = data; 
} 

void dummy(void) 
{ 
    node<int> intnode(0); 
    node<double> doublenode(0.0); 
} 
1
// You can put templates declaration in header and definition in source 
// node.h or wherever you include file gets included 
extern template class node<int>; 

// node.cpp or where ever source file you want to use it 
// But use it only once for each type of generated class 
template class node<int>; 
関連する問題