【问题标题】:Undefined references to member functions of a class template对类模板的成员函数的未定义引用
【发布时间】:2012-03-10 06:25:09
【问题描述】:

我想在模板类方法中使用迭代器。 这是我的代码:(testclass.h)

template<typename T, typename container>
class TestClassX
{
public:
    void gen(typename container::iterator first );
};

和文件 testclass.cpp:

template<typename T, typename container>
void TestClassX<T, container>::gen(typename container::iterator first)
{

}

当我尝试运行它时:

TestClassX<unsigned, std::vector<unsigned> > testx;
testx.gen(it);

我收到一个错误:

Error:undefined reference to `TestClassX<unsigned int, std::vector<unsigned int, std::allocator<unsigned int> > >::gen(__gnu_cxx::__normal_iterator<unsigned int*, std::vector<unsigned int, std::allocator<unsigned int> > >)'

我使用 mingw32 4.4

我想要一个可以写入不同容器的类,例如 std::vector、std::list、QVector 或 QList,所有这些容器都具有 STL 样式的迭代器。

【问题讨论】:

标签: c++ templates stl containers


【解决方案1】:

如前所述,模板实例化时定义必须存在于同一个编译单元中。

我个人更喜欢将定义与声明分开。
这样可以保持头文件更干净,并在视觉上将接口与实现分开。

因此,一个解决方案可以如下:

//TestClass.hpp

//Interface:
template<typename T>
class TestClassX
{
public:
    void gen(int a);
    //more declaraions...
}; 

//Implementations:
template<typename T>
void TestClassX<T>::gen(int a)
{
    //beautiful code
}

您可以将实现和接口放在单独的文件中 (即分别为 TestClass.hppITestClass.hpp)。
TestClass.hpp 最初将 #include ITestClass.hpp 然后定义函数,如上例所示。
然后,客户只需要#include TestClass.hpp

【讨论】:

    【解决方案2】:

    模板类方法不需要在头文件中定义。但是如果你这样做,你需要定义一个单独的编译单元(例如templates.cpp)并包含模板类的源代码文件(例如#include "container.cpp" // .cpp 不是.hpp 文件) 那么您需要定义您正在使用的模板的实例(例如,模板类 Container;)。 您还需要定义模板类的对象(例如链接)。在这种特殊情况下,由于我们使用指向该对象的指针(例如,在 Container 中的 Link*),我们只需要“前向声明”该对象。

    这是完整的 template.cpp 文件。您将编译并与其余代码链接。

    class Link;
    #include "Container.cpp"    // use the source code, not the header
    template class Container<Link*>; 
    

    我喜欢使用这种方法,因为它可以防止编译器自动生成模板类实例,并在找不到它时通知您。

    使用选项 -fno-implicit-templates 与 gcc 一起编译。

    当您构建时,所有内容都将正常编译,但收集器将为使用该模板的所有对象重新编译 templates.cpp 文件。

    【讨论】:

      【解决方案3】:

      模板类方法必须在头文件中定义。当您使用模板类时,编译器实际上会为给定的模板参数编译该类的一个版本。因此,在包含头文件时,要求每个方法的主体都可用。

      删除您的源文件并将正文包含在 testclass.h 中:

      template<typename T, typename container>
      class TestClassX
      {
      public:
          void gen(typename container::iterator first ) {
      
          }
      };
      

      【讨论】:

      • 模板类方法不需要在头文件中定义。你只需要让链接器找到它。同意@Thaddeus
      猜你喜欢
      • 2011-05-05
      • 1970-01-01
      • 1970-01-01
      • 2011-11-04
      • 1970-01-01
      • 1970-01-01
      • 2017-05-27
      • 2019-04-29
      • 1970-01-01
      相关资源
      最近更新 更多