所以,我要冒昧地说你已经在 CPP 文件中定义了一个模板函数,这意味着它最终会在不同的翻译单元中结束。这是一个简单的例子:
标头,example.h
#ifndef EXAMPLE_H
#define EXAMPLE_H
template<int TValue>
class example
{
public:
int get_tvalue();
};
#endif
源文件 example.cpp
#include "example.h"
template<int TValue>
int example<TValue>::get_tvalue()
{
return TValue;
}
还有另一个源文件 main.cpp
#include "example.h"
int main()
{
example<5> instance;
instance.get_tvalue();
return 0;
}
如果我使用 GCC 将它们编译在一起,我会得到undefined reference to 'example<5>::get_tvalue()'
. 这是因为模板类的实例化方式。模板类定义就是……一个模板,而不是一个实际的类。当该类的参数化(或特别是完全专业化)定义出现时,将创建实际的类定义,在这种情况下,example<5>
. 完全专业化的类定义只存在于 main.cpp 中……example.cpp 中没有这样的类!Example.cpp 仅包含模板,没有专业化。这意味着该函数get_tvalue
未example<5>
在 main.cpp 中定义,因此出现错误。
您可以通过以下两种方式之一解决此问题。第一种方法是始终在其头文件中定义整个模板类。例如,这是使用 STL 容器的方式。另一种方法是强制在 example.cpp 中创建参数化类...您可以通过添加
template class example<5>;
到 example.cpp 的末尾。因为现在example<5>
在 example.cpp 中有一个实际的类定义,所以您还将获得一个实际的函数定义example<5>::get_tvalue
,当您的翻译单元 main.o 和 example.o 在编译步骤结束时链接在一起时,一切都会好起来的。
显然,在大多数情况下,这将是一个糟糕的方法,但在您的模板参数仅采用小范围值的情况下,它可以工作。将整个类放在头文件中可能是最简单、最安全和最灵活的。