任何人都可以说明原因吗?
答案 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)
您是否在问为什么模板主体必须位于标题文件中?这是因为编译器需要同时知道正文和模板参数才能生成机器代码。模板参数在使用模板(实例化)的地方是已知的。这给你一个简单的案例和两个非平凡的案例:
答案 2 :(得分:1)
对您的问题的简短回答是,模板类的声明和定义没有义务在相同的源文件中。
事实上,我认为这是一件坏事,但它完全可以理解,因为单独使用它们非常困难(但可以做到!)。
编辑
假设你有
只需在main.cpp中包含myTemplateClass.h并按如下方式创建myTemplateClassInt.cpp:
#include "myTemplateClass.hpp"
template MyTemplateClass<int>;
这样做,您告诉编译器为模板参数“int”实例化MyTemplateClass的所有模板方法。由于它可以访问myTemplateClass.hpp,所以这些方法将完美无缺地生成......并且链接器不会抱怨。
当然,这种方法要求您使用定义模板类的实例化版本的地方。