编译多个文件时出现奇怪的未定义引用错误

问题描述:

我想编写一个玩具程序来运行C++,但是我得到了一个奇怪的未定义的引用错误,我无法解决。编译多个文件时出现奇怪的未定义引用错误

我的代码由3个文件:

ex13_6.h:

#include<vector> 

namespace ex13_6 { 
    template<class T> class Cmp { 
    public: 
     static int eq(T a, T b) {return a == b;} 
     static int lt(T a, T b) {return a < b;} 
    }; 

    template<class T, class C = Cmp<T> > void bubble_sort(std::vector<T> &v); 
} 

ex13_6.cpp

#include<vector> 
#include"ex13_6.h" 

namespace ex13_6 { 
    template<class T, class C = Cmp<T> > void bubble_sort(std::vector<T> &v) { 
     int s = v.size(); 
     T swap; 
     for (int i=0; i<s; i++) { 
      for (int j=0; j<s; j++) { 
       if (C::lt(v.at(j), v.at(i))) { 
        swap = v.at(i); 
        v.at(i) = v.at(j); 
        v.at(j) = swap; 
       } 
      } 
     } 
    } 
} 

main.cpp中:

#include"ex13_6.h" 
#include<iostream> 
#include<vector> 

using namespace std; 
using namespace ex13_6; 

int main() { 
    // Sort using default comparison for int 
    vector<int> v_int; 
    for (int i=0; i<10; i++) { 
     v_int.push_back(10-i); 
    } 
    bubble_sort(v_int); 
    cout << "sort of int vector:\n"; 
    for (vector<int>::const_iterator it = v_int.begin(); it != v_int.end(); it++) { 
     cout << ' ' << *it; 
    } 
    cout << '\n'; 
} 

而且我编译使用:

g++ main.cpp -o main -std=gnu++0x ex13_6.cpp 

以下是错误消息:

/tmp/ccRwO7Mf.o: In function `main': 
main.cpp:(.text+0x5a): undefined reference to `void ex13_6::bubble_sort<int, ex13_6::Cmp<int> >(std::vector<int, std::allocator<int> >&)' 
collect2: ld returned 1 exit status 

我真的很感激任何帮助!

+4

您可能需要在'ex13_6.cpp'中显式模板实例,或者您应该将模板函数的实现移动到头文件'ex13_6.h'中。请参阅:http://*.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file – jxh 2013-04-30 20:16:16

+0

谢谢@ user315052。但为什么我不能将通用模板函数定义放在ex13_6.cpp中? – user690421 2013-04-30 20:18:27

+0

@ user690421:你可以,但你需要一个明确的实例,正如我所解释的。看到引用SO问题。 – jxh 2013-04-30 20:19:45

移动你的bubble_sort模板的实施到你的头文件。

模板不像Java的泛型,所有的奇迹都发生在C++的编译时。为了使编译器为每个模板实例化生成代码,它必须是可见的,为此,它必须位于标题(或其他文件)中,并且包含在使用它的每个翻译单元中。

你的模板函数的定义应该是在ex13_6.h文件:

#include<vector> 

namespace ex13_6 { 
    template<class T> class Cmp { 
    public: 
     static int eq(T a, T b) {return a == b;} 
     static int lt(T a, T b) {return a < b;} 
    }; 

    template<class T, class C = Cmp<T> > void bubble_sort(std::vector<T> &v) { 
     int s = v.size(); 
     T swap; 
     for (int i=0; i<s; i++) { 
      for (int j=0; j<s; j++) { 
       if (C::lt(v.at(j), v.at(i))) { 
        swap = v.at(i); 
        v.at(i) = v.at(j); 
        v.at(j) = swap; 
       } 
      } 
     } 
    } 
} 

您需要将模板实现放在头文件中。

当实例化一个模板时,编译器需要“看”实现,所以如果你只包含头部,实现需要在那里。

请勿包含.cpp文件。