2013-04-05 94 views
1

我開發了一個使用C++模板處理多個類型{int,float,double}的數組庫。我將結構和函數的定義和聲明存儲在文件Util.h和Util.cpp中。我在arraySample.cpp中調用它。但是,我無法編譯該項目。 ++說未定義的參考printArray在C++中編譯模板結構

錯誤消息摹

make all 
g++ -O2 -g -Wall -fmessage-length=0 -c -o arraySample.o arraySample.cpp 
g++ -O2 -g -Wall -fmessage-length=0 -c -o Util.o Util.cpp 
g++ -o arraySample arraySample.o Util.o 
arraySample.o: In function `main': 
/home/vtvan/Desktop/workspace/arraySample/arraySample.cpp:15: undefined reference to `int printArray<double>(Array<double>)' 
/home/vtvan/Desktop/workspace/arraySample/arraySample.cpp:22: undefined reference to `int printArray<int>(Array<int>)' 
collect2: ld returned 1 exit status 
make: *** [arraySample] Error 1 

請幫我解決這個問題,我已經嘗試了很多次,但不能修復它。奇怪的是,當我將3個文件組合在一起時,它可以很好地工作。所以請給我一些解決方案。我在這裏附上3個文件的源代碼供您參考。

非常感謝,我期待着您的回覆。

Util.h

#ifndef UTIL_H_ 
#define UTIL_H_ 

#include <stdio.h> 
#include <stdlib.h> 
#include <string> 
#include <typeinfo> 

#define ARRAYMAXNDIMS 3 

// multi-dimensional array 
template <typename T> 
struct Array { 
    T *x; 
    int size; 
    int nDims; 
    int N[ARRAYMAXNDIMS]; 
}; 
template <typename T> int printArray(Array<T> A); 

#endif /* UTIL_H_ */ 

Util.cpp

#include <stdio.h> 
#include <stdlib.h> 
#include <string> 
#include <typeinfo> 

#include "Util.h" 

template <typename T> int printArray(Array<T> A) { 

    int i = 0, j = 0; 
    int k,l; 

    std::string typeT = typeid(T).name(); 

    std::string format(" %9f"); 

    if (!typeT.compare("i")) 
      format = " %d"; 

    printf("Array with dimension (%d",A.N[0]); 
    k=1; 
    while(k<A.nDims && k<ARRAYMAXNDIMS){ 
    printf(",%d",A.N[k]); 
    k++; 
    } 
    printf(")\n"); 

    switch (A.nDims) { 
    case 1: // print 1D array 
    for(k=0;k<A.N[0];k++){ printf(" %9d",A.x[k]);} 
    printf("\n"); 
    return(1); 
    case 2: // print 2D array 
    for(k=0;k<A.N[0];k++){ 

     for(l=0;l<A.N[1];l++) { 

      printf(format.c_str(),A.x[k+l*A.N[0]]); 
     } 
     printf("\n"); 
    } 
    return(1); 
    case 3: // print last 2 dimensions of a 3D array, where the index of the first dimension is i 
    if(i<0 || i>=A.N[0]) { 
     printf("index %d is outside the range of indices for the first dimension, i.e. [0:%d]\n",i,A.N[0]-1); 
     return(0); 
    } 
    printf("printing slice (%d,:,:)\n",i); 
    for(k=0;k<A.N[1];k++){ 
//  printf("%5d ",k); 
     for(l=0;l<A.N[2];l++) printf(" %9d",A.x[i+k*A.N[0]+l*A.N[0]*A.N[1]]); 
     printf("\n"); 
    } 
    return(1); 
    } 
} 

arraySample.cpp

#include <stdio.h> 
#include <stdlib.h> 

#include "Util.h" 

int main(void) { 

    Array<double> a; 

    a.nDims = 2; a.N[0] = 2; a.N[1] = 2; a.size = 4; 
    a.x = (double *)calloc(a.size,sizeof(double)); 
    a.x[0] = 1.23; a.x[1] = 2.23; a.x[2] = 3.23; a.x[3] = 5.23; 

    printArray(a); 

    Array<int> b; 
    b.nDims = 2; b.N[0] = 2; b.N[1] = 2; b.size = 4; 
    b.x = (int *)calloc(b.size,sizeof(int)); 
    b.x[0] = 1; b.x[1] = 2; b.x[2] = 3; b.x[3] = 5; 

    printArray(b); 

     return 0; 
} 
+1

定義,不僅僅是模板的聲明需要在.h文件中,因爲它需要在任何使用它的源文件中可見。 – jcoder 2013-04-05 12:43:42

+2

[爲什麼只能在頭文件中實現模板?](http://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – juanchopanza 2013-04-05 12:48:56

+0

我開始懷疑爲什麼我們最近每天都會收到這個問題... – Quentin 2015-06-05 14:09:21

回答

0

你應該在頭文件中定義模板功能printArray。只需將所有內容從Util.cpp移動到Util.h即可。

想想這樣。當編譯器正在編譯main.cpp時,它會到達printArray(a),然後想要將printArray模板實例化爲Tdouble。但是,它看不到該函數的定義,因此無法生成相應的代碼。因此,爲了使編譯器在此時可以看到函數實現,您應該將其放在標題中。

即達到完全相同的事情是#include <Util.cpp>Util.h(而不是在#include <Util.h>Util.cpp頂部)的底部的另一種。但是,相當普遍的做法是將模板實現文件替換爲.tpp擴展名。這使得這種關係更加清晰。

+0

非常感謝您給我解決方案。現在我可以編譯項目了!謝謝。 – andycandy 2013-04-05 13:14:29

0

您已經以某種方式回答了您自己的問題。您需要通過剪切並粘貼代碼或在util.h文件中使用#include指令來將util.cpp代碼與util.h文件相結合。然後,當你在arraySample.cpp中包含util.h文件時,你會得到想要的效果。 有關這方面的解釋和一些歷史記錄,請參閱Vandevoorde和Josuttis的「C++模板」第6章。