一 :概念:模板是泛型编程的基础,所谓泛型编程就是编写与类型无关的逻辑代码,是一种复用的方式,模板分为模板函数和模板类
二:模板函数
1:模板函数格式:
2:模板函数的实例化
<1>.隐式实例化------》推演为实例化一个步骤,推演形参类型
<2>显示实例化
三:模板类
1:模板类格式:
2:模板的模板参数------容器适配器,在上一篇博客中有
//template<class T,size_t M>
template<class T, size_t M=10>//带缺省的模板参数
class SeqList
{
public:
SeqList();
~SeqList();
private:
T _array[M];
int _size;
};
void test()
{
SeqList<int, 10>s1;
SeqList<int>s2;
}
template <class T,int value>
T ADD(const T&x)
{
return value + x;
}
(3)浮点数和类对象是不允许作为非类型模板参数的
template<class T,double Max>
template <class T,string name>
分离编译是指一个完整的程序或项目由若干个源文件共同实现,每个源文件单独编译生成目标文件,最后将该项目的所有目标文件链接成一个单一的可执行文件的过程每个.cpp源文件经过预处理,它所包含的.h文件的代码都会被展开到其中。再经过编译器的编译,汇编等过程,将该.cpp文件转变为.obj文件,这时此文件已将变成二进制文件,本身包含的就是二进制代码。这时,该文件还不一定能够执行,因为并不保证其中一定有main函数,或者该源文件中的函数可能引用了另一个源文件中定义的某个变量或者函数调用,又或者在程序中可能调用了某个库文件中的函数,等等。这些都要通过链接器将该项目中的所有目标文件连接成一个单一的可执行文件来解决。main.cpp包含的Template.h头文件只有对F1()函数的声明,所以在main.cpp中没有任何与F1()函数定义相关的代码,这里就会把F1()函数看作外部链接类型。在主函数调用F1()函数时,会产生如下图红框的call命令,当然这里的地址是一个虚假的地址。链接器在Template.obj文件中找到F1()函数的实现代码,将call F1()地址通过jmp指令切换成真正的F1函数地址。
Template.h
#pragma once
#include<iostream>
using namespace std;
void F1();
template<class T>
void F2(const T& x);
Template.cpp
#include"Template.h"
void F1()
{
cout << "F1()" << endl;
}
template<class T>
void F2(const T& x)
{
cout << "F2()" << endl;
}
Main.cpp
#include"Template.h"
int main()
{
F1();
F2(10);
system("pause");
return 0;
}
看上面程序,如果只调用普通函数F1可以成功运行,但是调F2模板函数就不行,F2不支持分离编译。
为什莫模板函数不支持分离编译?怎样解决呢?
原因:因为在template.cpp中没有实例化,不生成代码。在Main.cpp中实例化。但是在链接前是不交互的,因此链接时找不到(因为没有)出错。
在执行main函数的语句中,要调用void F2<int>(const int& x),链接器在main.obj中找不到void F2<int>(const int&x)的定义,因此会去Template.obj中找。大家都知道模板只有在被实例化才生成代码,而在template.cpp中并没有实例化。虽然在main.cpp中实例化。但在链接之前两个文件是不交互的,链接器在template.obj中找不到函数实现的二进制代码。因此链接时会出错。
解决办法:1.在template.cpp中显示实例化
如下图:
显示实例化
2.把声明和定义都放在.h中
如下图: