模板显式实例化 explicit template instantiation

来源:互联网 发布:杭州富谦网络 编辑:程序博客网 时间:2024/05/01 19:11

众所周知,C++中模板的声明与定义分离时,需要使用显式实例化,否则就会出现链接错误。这个星期的程设作业中就出现了显式实例化,而且是TA为我们先写好的,我一开始也没在意,后来有人问到了这个问题,我才知道如果不写上的话会导致链接错误,于是搜索了一下原因,发现很少对原因有解释,于是打算讲一下我的理解。

http://www.cplusplus.com/forum/articles/14272/

首先感谢这篇文章的作者,我也是看了它才明白。

要理解这个问题,首先需要知道编译器是怎么处理template的。其实template跟普通的东西没什么区别,只是增加了一些参数,只是这些参数甚至可以是类型名而已,而编译器在编译时必须把模板实例化成具体的东西,这样才能被正常地调用(模板是编译时多态,不能在运行时再来根据参数类型进行调用,原因目前我还不知道)。实例化的过程,就是为可能将要用到的模板参数分别编译出这个模板的一个实例,类型的推断则由编译器对类型进行推断完成,比如int a, b; cmp(a, b); 那么编译器就会知道我们将要使用cmp<int>,然后帮我们把typename的参数都替换成int,编译出一个函数。

如果我们把实现与声明写在一起,那么定义也随之被include到了需要调用这个模板的地方,那么可以正常编译。问题就出现在我们把实现与声明写在.h和.cpp文件中的时候,当编译器编译实现文件时,里面只有定义而没有对模板的调用(文件之间是独立编译再链接的,所以不会去访问其他文件),编译器就不会对模板进行实例化。到了链接时,要调用相应的模板的时候,就会因为找不到相应的东西而报错。

下面是我做的一个实验

//Example.htemplate<class T>class Test {    public:        Test(T a);};//Example.cpp#include "Example.h"template<class T>Test<T>::Test(T a) {    //do nothing...}//template class Test<int>;

当保留最后一行的时候,编译Example.cpp输出汇编语言会得到一大块东西,而注释掉最后一行后就只剩下

.file"Example.cpp".ident"GCC: (tdm64-2) 4.8.1"

显然是没有代码被生成的,当然也就出现链接错误

看完以后,你应该会知道,实际上应该说是定义与调用分离更正确,只是因为声明是需要include到需要调用模板的.cpp文件中的,如果把定义与声明写在一起,相当于把定义include到了调用的文件中罢了。

另外也可以去看看这篇文章,写得更加详细http://blog.csdn.net/flowshell/article/details/5999588

創用 CC 授權條款
本著作係採用創用 CC 姓名標示-非商業性 3.0 美國 授權條款授權.
0 0