为什么声明/定义必须都在c ++中的模板类的源文件中?

时间:2010-10-15 06:17:56

标签: c++ templates

任何人都可以说明原因吗?

3 个答案:

答案 0 :(得分:3)

源文件彼此独立编译成可执行代码,然后链接到主程序。另一方面,模板函数无法在没有模板参数的情况下编译。因此,使用它们的文件需要具有该代码才能进行编译。因此,函数需要在头文件中可见。

承诺的例子:

template<class T>
void swap(T & a, T & b)
{
    T temp = a;
    a = b;
    b = temp;
}

这里T类的唯一要求是它有一个公共赋值运算符(=)。这就是所有已经实施或构思过的课程。但是,每个类都以自己的方式实现赋值运算符。无法为swap&lt; int&gt;,swap&lt; double&gt;生成相同的机器代码并交换&lt; string&gt;。这些功能中的每一个都必须是唯一的。同时,编译器不可能预测到您可能传递给此函数的所有不同类型,因此它无法提前生成函数。所以它必须等到函数被调用,然后它才能被编译。

例如,假设我在“swap.h”中定义了上面的函数。然后在“main.cpp”中,我这样做:

int main()
{
    int a=5, b=10;
    double c=3.5, d=7.9;
    string s1="hello";
    string s2="world";

    swap(a,b);
    swap(c,d);
    swap(s1,s2);
}

在此示例中,创建了3个不同的功能。一个交换整数,一个交换双打,一个交换字符串。为了创建这些函数,编译器需要能够看到模板代码。如果它在一个单独的源文件中,例如“swap.cpp”,编译器将无法看到它,因为正如我之前所说的,每个源文件都是相互独立编译的。

答案 1 :(得分:2)

您是否在问为什么模板主体必须位于标题文件中?这是因为编译器需要同时知道正文和模板参数才能生成机器代码。模板参数在使用模板(实例化)的地方是已知的。这给你一个简单的案例和两个非平凡的案例:

  1. (Trivial)模板仅用于一个源文件,因此正文可以位于同一个源文件中。
  2. 在每次使用时都可以使用正文,这通常意味着在头文件中。
  3. 在包含正文的源文件中,显式实例化每个所需的模板参数组合。

答案 2 :(得分:1)

对您的问题的简短回答是,模板类的声明和定义没有义务在相同的源文件中。

事实上,我认为这是一件坏事,但它完全可以理解,因为单独使用它们非常困难(但可以做到!)。

编辑

假设你有

  • myTemplateClass.h,它声明了一个模板类MyTemplateClass
  • myTemplateClass.hpp,它定义了它的类成员(包括myTemplateClass.h)
  • 在main.cpp
  • 中使用MyTemplateClass

只需在main.cpp中包含myTemplateClass.h并按如下方式创建myTemplateClassInt.cpp:

#include "myTemplateClass.hpp"

template MyTemplateClass<int>;

这样做,您告诉编译器为模板参数“int”实例化MyTemplateClass的所有模板方法。由于它可以访问myTemplateClass.hpp,所以这些方法将完美无缺地生成......并且链接器不会抱怨。

当然,这种方法要求您使用定义模板类的实例化版本的地方。