2013-04-05 53 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章。