在C ++中如何正确定义和实现模板类?

时间:2013-09-26 16:42:59

标签: c++ templates

我最近决定通过编写简单的结构来简化C ++开发,从而进行一些个人C ++实践。我的第一次尝试是编写一个简单的LinkedList,但将其定义为模板类,以便它可以处理多种数据类型。在这样做时,我做了标准的做法,在头文件中定义类并在cpp文件中实现它,然后我使用make来构建它(使用686-apple-darwin11-llvm-g++-4.2 (GCC) 4.2.1)。至于构建C ++文件(包括Node.cppLinkedList.cppLinkedListIterator.cpp,一切正常,没有任何抱怨。然后我介绍main.cpp,其中包含主要方法并尝试过创建一个LinkedList<string>(有效)然后尝试调用它的长度函数,我已经定义并实现了它:

// Other code here
LinkedList<string> *list = new LinkedList<string>();
cout << "Initial length: " << list->length() << endl;
delete list;
list = NULL; // I had defined NULL to be 0, pre 4.6 compiler so nullptr wasn't available
// End the main function

这引发了一个错误,即没有为模板length()类定义LinkedList<string>函数,所以我开始研究,我学到了模板类不能像标准标准头/实现格式那样定义C ++类,但这些响应中没有一个(主要是在这里)解决了如何正确处理模板类。因此,为了完成我的个人练习,我删除了标题,并在cpp文件中定义并实现了类。那里的一切都很好。

有一些&#34;解决方案&#34;据说可以将实现与定义分开,例如在头文件的末尾包含cpp文件(这对我来说无法工作),或者,如果你只希望你的类使用特定类型,则声明静态模板版本在您的头文件的基础上的类,如:

// Define a template class
template LinkedList<string>;
template LinkedList<int>;
// etc...

我没有尝试过(它可能有效,而且我只是做个人运动,这是完全可以接受的)因为这只是感觉不对。如果将其锁定为某些类型,为什么要创建模板类?我意识到你可以很容易地将它锁定到你需要的所有主要类型中,为你提供一个数据类型的定义,但它并不适合我这样做。

TL; DR 最后我的问题是,在其他人会使用的某种应用程序/库中定义模板类和实现模板类的正确方法是什么?

2 个答案:

答案 0 :(得分:3)

您需要在标题中放置所有内容 - 类定义类代码。为了了解原因,想象一个简单的案例:

// in .hpp
template <typename T>
T increment(T x);

// in .cpp
template <typename T>
T increment(T x) { return x + 1; }

现在只编译一次.cpp。它应该为increment函数生成什么代码? +运算符可以是浮点加法,或整数加法,或短整数,甚至是重载operator+

然后考虑一下你使用 increment函数的其他.cpp文件:

// some other .cpp file
#include "increment.hpp"
...
  increment(a);

点,编译器知道a是什么类型,因此它可以为increment函数生成正确的代码。但是它不知道increment函数的样子,因为它只看到.hpp文件而increment的代码在 .cpp 文件中。

因此,使其工作的唯一方法是将声明和代码放在.hpp文件中,以便每次使用时,您都有定义,编译器可以生成适用于您正在使用的类型的正确版本。

答案 1 :(得分:2)

模板必须在实例化时可见。没有显式实例化,基本上意味着成员函数定义必须在标题中可供其他翻译单元实例化。