【问题标题】:templates - undefined reference error模板 - 未定义的引用错误
【发布时间】:2012-06-19 10:47:25
【问题描述】:

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

#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&lt;int, 5u&gt;::Print() const'的引用。这可能是什么原因? 谢谢!

【问题讨论】:

  • 您能否提供一些产生错误的代码,例如。调用 Cluster::Print?
  • ideone.com/cMTih 为我工作。
  • 编辑您的原始评论将是包含格式良好的代码的最佳方式;-)(另外,这不是错误的最小示例,因为它有大量对您没有的函数的引用' t 提供给我们)。此外,注释掉 FillVectorKNN 调用并定义 cluster_size 给我留下了构建良好的代码......
  • 再想一想...您的Cluster 定义真的都在同一个头文件中,还是您的Print 函数体在CPP 文件中?因为您会遇到模板实例化问题,因为您的模板类的一部分分散在翻译单元中。如果您不小心的话。
  • –1 表示缺少 SSCCE

标签: c++ templates


【解决方案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&lt;5&gt;::get_tvalue()'。这是因为模板类的实例化方式。模板类定义就是……一个模板,而不是一个实际的类。实际的类定义是在该类的参数化(或特别是完全专业化)定义出现时创建的,在本例中为example&lt;5&gt;。完全专业化的类定义只存在于 main.cpp 中……example.cpp 中没有这样的类! Example.cpp 仅包含模板,没有专业化。这意味着函数 get_tvalue 没有在 main.cpp 中为 example&lt;5&gt; 定义,因此出现错误。

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

template class example<5>;

到 example.cpp 的末尾。因为现在在 example.cpp 中有一个 example&lt;5&gt; 的实际类定义,所以您还将获得 example&lt;5&gt;::get_tvalue 的实际函数定义,并且当您的翻译单元 main.o 和 example.o 在编译步骤结束时链接在一起时一切都会好起来的。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-01-15
    • 2010-11-09
    • 2021-12-21
    • 2021-10-22
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多