可能重复:
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)
。我已经尝试了几件事,但没有任何真正的知识来支持我的工作。如果有人能解释我发生了什么,我将非常感激。
答案 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)