2011-07-03 12 views
1

皆さん、私はちょうどいくつかのC++テンプレートを練習したいと思っていましたが、リンカエラーが発生します。誰でも助けてくれますか?ここ は私のコードです:あなたは、私はUbuntuの10.04とGNU C++コンパイラを使用しています見ることができるようにC++テンプレートクラスの問題

g++ main.cpp -c 
g++ MyClass.cpp -c 
g++ main.o MyClass.o -o Out 
main.o: In function `main': 
main.cpp:(.text+0x1a): undefined reference to `MyClass<int>::MyClass(int)' 
main.cpp:(.text+0x2b): undefined reference to `MyClass<int>::~MyClass()' 
collect2: ld returned 1 exit status 
make: *** [all] Error 1 

:ここ

// File: MyClass.h 
#ifndef _MYCLASS_H 
#define _MYCLASS_H 
template<class T> class MyClass { 
T value; 
public: 
MyClass(T v); 
~MyClass(); 
}; 
#endif // _MYCLASS_H 

// File: MyClass.cpp 
#include "MyClass.h" 
template<class T> MyClass<T>::MyClass(T v) { 
value = v; 
} 
template<class T> MyClass<T>::~MyClass() { 

} 

// File: main.cpp 
#include "MyClass.h" 
int main() { 
MyClass<int> test(10); 
return 0; 
} 

は、コマンドライン出力です。 このコードで何か不足していますか?


お返事ありがとうございます。それは動作しますが、コードを保護する良い方法はありませんか? たとえば、非オープンソースライブラリを作成する場合はどうなりますか? コードを静的ライブラリにエクスポートします。ライブラリを他のプロジェクトにリンクしてください。

+0

'MyClass.cpp'と' main.cpp'は別々に(異なる翻訳単位)コンパイルされるので、あなたのコンパイラが 'MyClass.cpp'をコンパイルするとき、どの引数がインスタンス化されなければならないのか分かりません。定義と宣言を 'main.cpp'に移す必要があります。 –

答えて

5

ヘッダーに完全なテンプレートを入れる必要があります。コンパイラはテンプレートインスタンスのサイトでテンプレートメソッドの本体(main.cpp)を表示する必要があります。例えば、C++ FAQを参照されたい。

+0

右ですが、私は 'MyClass.cpp'を' MyClass_impl.h'に、 '#include" MyClass_impl.hを 'MyClass.h'の末尾に改名することを提案します。これにより、読みやすくするために宣言と実装を別々のファイルに保持することができます。 –

1

テンプレートクラスとインラインメソッドをヘッダーファイルに配置する必要があります。あなたはそのケースで定義と実装を分離することはできません。

1

@Nikolai N Fetissovは正しい解決策を持っています。私は、これまでこれを行うには、その良い方法を追加するには、実装を維持したいとテンプレート関数定義を分離場合は、MyClass.hxxに実装を置くことができるということであり、あなたのMyClass.h

// File: MyClass.h 
#ifndef _MYCLASS_H 
#define _MYCLASS_H 

template<class T> class MyClass 
{ 
    T value; 
public: 
    MyClass(T v); 
    ~MyClass(); 
}; 

#include "MyClass.hxx" /// <--- like this 
#endif // _MYCLASS_H 
の終わりにそれが含まれるであろう
0

テンプレートが何であるかを覚えておくことが重要です。必要に応じてコードを生成するためのテンプレートです。コード自体ではありません。

したがって、テンプレートクラスを宣言し、それらのメソッドの実装を記述しても、そのクラスのオブジェクトコードは生成されません。必要に応じてテンプレートを提供するだけです。

実際の引数を使用してテンプレートクラスをインスタンス化すると、コンパイラはテンプレートクラスからコードを生成します。これを行うには、テンプレートを見ることができる必要があります。しかし、.hファイルだけを#includeで編集し、.cppファイル内のメソッドの実装を行ったため、コンパイラは関数の実装のオブジェクトコードを生成することができません。次に、リンカがそれらの定義を探すとき、それを見つけられません。

これは、他の回答と同じ結果になるための長年にわたる方法です。クラスの宣言でヘッダーファイルに実装を配置する必要があります。しかし、それがなぜそれを知るのに役立つかもしれません。