テンプレートクラス別コンパイル問題
テンプレートクラス宣言と実装の分離(すなわち.hファイルに宣言し、.cppファイルに実装する)についてのテスト.
最近はテンプレートクラスを書くときに、テンプレート宣言とテンプレートを別々にコンパイルしておとなしくコンパイルを実現していますが.ヒントを見ると、実装されていない関数にリンクされているはずです.
ネットで調べてみると、精巧な解釈がたくさん見つかりました.
テンプレートの具体的な定義は、テンプレートパラメータが決定されてからインスタンス化されるためです.テンプレートのインスタンス化中(main関数などですが、テンプレート宣言関数のみが含まれます).インスタンス化を含む.cppファイルをコンパイルする.oファイルは,クラス関数のエントリアドレスを残して埋め込みを待つ.
一般、一般関数を含む.cppファイルをコンパイルする.oファイルの場合.関数は決定され、バイナリコードにコンパイルできます.そして、この関数を呼び出す関数をリンクプログラムに埋め込む関数エントリアドレスがある.oファイルにあります.
そして関数呼び出しに成功しました.
ただし、テンプレートクラスの実装については.コンパイルoファイルの場合、インスタンス化されていません.すなわち,テンプレートクラスの実装関数は具体的なテンプレート関数が何であるかを知らず,真のタイプにインスタンス化できない.
(たとえば、Vectora;//パラメータはintにインスタンス化され、vectorは1つのタイプ(内蔵タイプdoubleと同じ)になります.しかし、インスタンス化されない前に、関数は不確定です.まだバイナリファイルにコンパイルされていません.したがって、関数のエントリアドレスは提供されません.エントリアドレスがないため、リンクプログラムはmain関数をインスタンス化して具体的なタイプのテンプレートを探して実装関数を探すときに見つからず、リンクエラーを提示します.どこが粗末なのか知っている以上,問題を解決することができる.解決策はテンプレートをインスタンス化することである.cppファイルは関数実装を見ることができます.ここには2つの方法がある.1、直接に関数宣言と関数実現を全部同じにする.hファイルの中.このように引用する.hファイルの場合、宣言と実装はインスタンス化されたものに直接展開される.cppファイルの中でこのようにコンパイルすると、関数のエントリアドレスが見つかります.2、関数宣言と関数実装は別々に実装される.テンプレートをインスタンス化する場所#include"xxx.cpp"は、直接含む.cppファイルは、関数エントリも見つかります.私が下でテストしたように.実は、私は前に一般的な文章を見て、声明と実現を同じにすればと言いました.hファイルの中には、違います.cppファイルで異なるパラメータでテンプレートを実装すると、定義の誤りが繰り返されます.しかし、私は出会ったことがありません.後で気づいたら補充して帰りましょう.
templateclass.h
templateclass.cpp
int.cpp
mainfun.cpp
//makefile
参照先:
テンプレート分離コンパイルを超通俗的に解釈する
http://blog.csdn.net/pongba/article/details/19130
最近はテンプレートクラスを書くときに、テンプレート宣言とテンプレートを別々にコンパイルしておとなしくコンパイルを実現していますが.ヒントを見ると、実装されていない関数にリンクされているはずです.
ネットで調べてみると、精巧な解釈がたくさん見つかりました.
テンプレートの具体的な定義は、テンプレートパラメータが決定されてからインスタンス化されるためです.テンプレートのインスタンス化中(main関数などですが、テンプレート宣言関数のみが含まれます).インスタンス化を含む.cppファイルをコンパイルする.oファイルは,クラス関数のエントリアドレスを残して埋め込みを待つ.
一般、一般関数を含む.cppファイルをコンパイルする.oファイルの場合.関数は決定され、バイナリコードにコンパイルできます.そして、この関数を呼び出す関数をリンクプログラムに埋め込む関数エントリアドレスがある.oファイルにあります.
そして関数呼び出しに成功しました.
ただし、テンプレートクラスの実装については.コンパイルoファイルの場合、インスタンス化されていません.すなわち,テンプレートクラスの実装関数は具体的なテンプレート関数が何であるかを知らず,真のタイプにインスタンス化できない.
(たとえば、Vector
templateclass.h
#ifndef _TEM_H__
#define _TEM_H__
#include <iostream>
using namespace std;
template <class Elem>
class List {
private:
Elem data;
public:
List(Elem a ) {
data = a;
}
void print( void );
};
//#include "templateclass.cpp"
#endif
templateclass.cpp
#include "templateclass.h"
template <class Elem>
void List<Elem>::print( ) {
cout << data << endl;
}
double.cpp #include "templateclass.h"
#include "templateclass.cpp"
void doubleprint( double para ) {
List<double> object( para );
object.print( );
}
int.cpp
#include "templateclass.h"
#include "templateclass.cpp"
void intprint( int para ) {
List<int> object( para );
object.print( );
}
mainfun.cpp
//#include <iostream>
//using namespace std;
void doubleprint( double );
void intprint( int );
int main( int argc, char *argv[] ) {
doubleprint( 3.5 );
intprint( 19 );
return 0;
}
//makefile
tao: double.o int.o mainfun.o templateclass.o
g++ -o tao double.o int.o mainfun.o templateclass.o
double.o: templateclass.h double.cpp
g++ -c double.cpp
int.o: templateclass.h int.cpp
g++ -c int.cpp
templateclass.o: templateclass.h templateclass.cpp
g++ -c templateclass.cpp
mainfun.o: double.cpp int.cpp mainfun.cpp
g++ -c mainfun.cpp
参照先:
テンプレート分離コンパイルを超通俗的に解釈する
http://blog.csdn.net/pongba/article/details/19130