模板的分离编译问题

一、下面我们主要讨论分析一下模板为什么不支持分离编译?

所谓的分离编译是指将声明和定义分开来写,即将一个函数的声明和定义放在.h和.cpp文件中。
写过模板的人应该都会发现当我们用上面的方式写一个函数的时候,只要在.cpp中包.h的头文件,就没什么问题,但是如果写模板的时候,就编译链接不过去,就如下面这个例子:

//func.h
#include<iostream>
template <class T>
void func(const T&);

//func.cpp
#include<iostream>
using namespace std;
#include"func.h"
template void func(const T& t)
{
    cout<<t<<endl;
}

//main.cpp
#include"func.h"
int main()
{
    func(3);
    getchar();
    return 0;
}

在分离编译模式下,func.cpp会生成一个目标文件func.obj,由于在func.cpp文件中,并中没有发生函数模板调用,所以不会将template实例化为template,也就是说在func.obj中无法找到关于模板函数func的实现代码,在源文件main.cpp中,虽然函数模板被调用,但由于没有模板代码,也不能将其实例化.这样,在链接的时候就会出现func没有被定义的错误。

二、解决方法

1.将函数模板的定义放到头文件中

一个简单的解决办法就是将函数模板func< T>的定义写到头文件func.h中。这样的话,只要包含了这个头文件,就会把函数模板的代码包含进来,一旦发生函数调用,就可以依据函数模板代码将其实例化。
这个办法虽然简单可行,但是有如下不足。
(1)函数模板的定义写进了头文件,暴露了函数模板的实现细节。
(2)不符合分离编译模式的规则,因为分离编译模式要求函数原型申明放在头文件,定义放在源文件。
注意:这样做,如果在多个目标文件中存在相同的函数模板实例化后的模板函数实体,连接时并不会报函数重定义的错误,这与普通函数不同,是C++对模板函数的特殊规定。

2.仍然采用分离编译模式

使用关键字export,在func.cpp里定义函数模板的时候,将函数模板头改为:

export template<class T> 
void func(const T& t); 

其实这样做是为了告诉编译器,这个函数模板可能在其他源文件中被实例化。但是。目前几乎所以的编译器都不支持关键字export,所以这种方法不推荐使用。

3.显示实例化

  显示实例化也称外部实例化。模板不支持分离编译的原因在于模板没有实例化,从而导致的一系列问题,因此,在不发生函数调用的时候将函数模板实例化,或者在不使用类模板的时候将类模板实例化能更好的解决问题。

在func.cpp中将函数模板func显示实例化为模板函数func

template void func<int>(const int &>;

这样,就可以在func.cpp产生模板函数func< int>的实例化代码,编译之后就会产生函数的二进制代码,供其它源文件连接,程序就可以正常运行。当类模板的成员函数的实现定义在源文件中,通过模板类的对象调用成员函数时也会出现找不到函数定义的错误,可以使用同样的方法解决,不再赘述。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值