C ++(gcc):对“Stack <int> :: Stack(int)'</int>的未定义引用

时间:2011-10-11 18:55:17

标签: c++ gcc

  

可能重复:
  Why can templates only be implemented in the header file?

我一直在努力解决这个问题,我已经在这里看了几个问题,但是对C ++不熟悉我还不能理解我错在哪里。

以下是代码,我从this page获取代码并尝试使其正常工作,但到目前为止我还不幸运:

stack.h

#ifndef STACK_H
#define STACK_H
template <class T>
class Stack {
  public:
    Stack(int n);
    ~Stack() { delete[] s; };
  private:
    T* s;
    int _top;
    int _size;
};
#endif // STACK_H

stack.cpp

#include "stack.h"
template <class T>
Stack<T>::Stack(int n) {
  _size = n;
  _top = -1;
  s = new T[_size];
}

的main.cpp

#include <iostream>
#include "stack.h"
using namespace std;
int main() {
  Stack<int> s(10); // undefined reference to `Stack<int>::Stack(int)'
  return 0;
}

当我编译(gcc 4.5.2)时,我收到一个错误:undefined reference to Stack<int>::Stack(int)。我已经尝试了几件事,但没有任何真正的知识来支持我的工作。如果有人能解释我发生了什么,我将非常感激。

3 个答案:

答案 0 :(得分:4)

如果cpp文件是一个专门的定义,你只能在cpp文件中有一个模板类定义 - 即你知道T是什么。

除此之外,您的案例属于此处,模板类的所有定义都必须放在头文件中。每次声明或定义新实例时,编译器都必须知道这些,因为类型和行为会发生变化。 cpp文件中的定义意味着不同的翻译单元,因此编译器可能无法了解您尝试应用于模板的每个T的行为。

答案 1 :(得分:1)

编译器在创建模板类时必须拥有所有相关信息,因此模板通常在其头文件中完全实现。

有几种方法可以实现这一点,内联函数,在头文件中定义模板函数,包括在单独文件中的实现(在头文件末尾,#include)等。

这是一个similar question,其中包含更多详细信息。

答案 2 :(得分:1)

在“stack.cpp”中无需编译。模板仅在实例化时编译。因此链接器找不到从未编译过的函数。

您无法使用模板将标头和源文件中的声明和实现分开。

你可以做的是将“stack.cpp”复制粘贴到“stack.h”的末尾。或者在“stack.h”的末尾包括“stack.cpp”,而不是反过来,这实现了相同的效果。在后一种情况下,更改“cpp”文件的扩展名可能是明智的(参见Including .cpp at end of template header file