templates - 未定义的引用错误

时间:2012-06-19 10:47:25

标签: c++ templates

我有以下简单的模板代码:

#ifndef CLUSTER_H
#define CLUSTER_H

#include <iostream>
#include <vector>

template <typename T, size_t K>
class Cluster
{
public:
    void Print() const;     
private:
    std::vector<T> objects;
};
template <typename T, size_t K>
void Cluster<T,K>::Print() const
{
    for (int i=0; i<objects.size(); i++)
    {
        T curr=objects[i];
        std::cout << curr << " ";
    }
    std::cout << std::endl;
}

#endif

由于某种原因,我收到以下错误:“未定义引用'Cluster<int, 5u>::Print() const'。这可能是什么原因? 谢谢!

1 个答案:

答案 0 :(得分:1)

所以,我将在这里说明你已经在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没有在main.cpp中为example<5>定义,因此错误。

您可以通过以下两种方式之一解决此问题。第一种方法是始终在其头文件中定义整个模板类。例如,这是使用STL容器完成的方式。另一种方法是强制在example.cpp中创建一个参数化类...你可以通过添加

来实现
template class example<5>;

到example.cpp的末尾。因为在example.cpp中现在有example<5>的实际类定义,所以您还将获得example<5>::get_tvalue的实际函数定义,以及当您的翻译单元main.o和example.o在最后链接在一起时编译步骤一切都会好的。

显然,在大多数情况下,这种方法很糟糕,但在模板参数只占用一小部分值的情况下,它可以正常工作。将整个类放在头文件中可能是最简单,最安全和最灵活的。