要编译成DLL,就要声明和实现分开。
首先文件组织是这样的(为了简化,没有加上编译成DLL的语句)
在 T.h 中(声明模板函数)
template<typename T>
T Max(T& t1,T& t2);
在 T.cpp 中(模板函数的实现)
#include"T.h"
template<typename T>
T Max(T& t1,T& t2)
{
}
编译 T.cpp 很好,通过编译
在 Main.cpp 中(用于测试的)
#include<iostream>
using namespace std;
#include"T.h"
int main()
{
}
编译 Main.cpp 很好,也通过编译
然后 链接运行程序
此时,产生链接错误了(Visual Studio 2008环境下)
1>Main.obj : error LNK2019: 无法解析的外部符号 "double __cdecl Max<double>(double &,double &)" (??$Max@N@@YANAAN0@Z),该符号在函数 _main 中被引用
1>Main.obj : error LNK2019: 无法解析的外部符号 "int __cdecl Max<int>(int &,int &)" (??$Max@H@@YAHAAH0@Z),该符号在函数 _main 中被引用
链接器根本没有找到那两个函数
发现模板的东西分开成 .h 和 .cpp 是不行的
因为模板是需要在编译时实现特例化的,光编译T.cpp是没有产生可用的函数的。
因此,模板函数/模板类也无法编译成DLL
Visual Studio 中的系统库中的STL(标准模板库)都是以源代码的形式呈现的(例如<map>里面可以看到源码的)
看来微软也没得好办法解决这个
所以一般而言 模板的东西 还是都直接写到 .h 就好了
至于说一定要分开成 .h 和 .cpp的话,用的时候需要#include".cpp"(这个方法很畸形,本质还是直接include了声明和实现,据说gcc可以分开成 .h 和 .cpp,没有测试过,应该只是编译器自动化的帮你include了)
当然这样还是不能编译成DLL的,我查阅了一下,实在想编译成DLL的话,必须在编译模板的时候就进行特例化(其实这样失去了模板的优势了,唯一好点的就是可以特例化多种形式)
在 原来的 T.cpp 中加上这段就可以特例化了(也可以加到 T.h 中)
template int Max<int>(int& ,int& ); //int特例化
template double Max<double>(double& ,double& ); //double特例化
这样编译链接运行,就可以了
要编译成DLL的话,加上DLL的那个关键字就可以了
#ifdef DLL_EXPORTS
#define DLLT_API __declspec(dllexport)
#else
#define DLL_API __declspec(dllimport)
#endif
C++现在这种编译时的模板化机制,岂不是让别个通用模板函数库的开发商只能开源了?