泛型编程
泛型编程,编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
- 可以理解为活字印刷术类似的方式。
函数模板
函数模板概念
函数模板,代表一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
解决函数作用相同,但是参数类型不同,得写好几个参数不同但函数功能相同的代码,函数模板就是解决这个问题。
本来应该我们做的重复的事情交给了编译器。
函数模板语法
template<typename T1,typename T2,...,typename Tn>
返回类型 函数名(参数列表){}
- typename是定义模板参数的关键字
- 也可以使用class,但不能是struct
函数模板使用案例
#include <stdio.h>
#include <iostream>
using namespace std;
//template<typename T>
template<class T>
//typename是定义模板参数的关键字,
//也可以使用class,但不能是struct
void Swap(T& left, T& right)
{T temp = left;left = right;right = temp;
}
int main()
{int a = 3, b = 5;Swap(a, b);cout << "a=" << a << " " << "b=" << b << endl;//a=5 b=3double d = 2.63, e = 9.35;Swap(d, e);cout << "d=" << d << " " << "e=" << e << endl;//d=9.35 e=2.63return 0;
}
函数模板原理
- 函数模板,本身并不是函数;
- 是编译器产生特定具体类型函数的模具;
- 在编译器编译阶段,编译器根据传入的实参类型来推演生成对应类型的函数。
- 例如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码。
函数模板实例化
用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显示实例化。
隐式实例化
隐式实例化,让编译器自己根据实参推演模板参数的实际类型。
template <typename T>
T Add(const T& left, const T& right)
{return left + right;
}
int main()
{int a1 = 10, a2 = 20;double d1 = 10.9, d2 = 45.8;//隐式实例化cout << Add(a1, a2) << endl; //30cout << Add(d1, d2) << endl;//56.7// Add(a1, d1) 会报错 // 编译器无法确定此处到底该是将T确定为int还是double// 两种处理方式:①用户强转 Add(a1, (int)d1) ;②显示实例化 Add<int>(a1, d1) //cout << Add(a1, d1) << endl;//56.7cout << Add(a1, (int)d1) << endl;//56.7return 0;
}
显示实例化
显示实例化,在函数名后的<>中指定模板参数的实际类型。
template <typename T>
T Add(const T& left, const T& right)
{return left + right;
}
int main()
{int a = 10;double d = 10.9;//显示实例化cout << Add<int>(a, d) << endl;//20return 0;
}
模板参数的匹配规则
- 一个非模板函数可以和一个同名模板函数同时存在。
非模板函数与同名模板函数同时存在时:
- 调用函数与非模板函数匹配时,编译器不需要推演特化;
- 有显示实例化,编译器进行函数模板推演;
- 优先调用非模板函数;
- 模板函数不允许自动类型转换,但普通函数可以进行自动类型转化。
类模板
将类中的成员变量或者成员函数的参数数据类型进行模板化。
类模板名字不是真正的类,实例化的结果才是真正的类。
类模板语法
- 类模板中函数放在类外进行定义时,需要加模板参数列表。
template<class T1,class T2,...,class Tn>
class 类模板名
{//类成员
};//类模板函数在类外定义,加模板参数列表
template<class T1,class T2,...,class Tn>
类模板名<T1/T2/.../Tn>::类模板成员函数名()
{函数功能
}int main()
{类模板名<实例化类型> 类对象实例化名字;//Date d;
}
类模板实例化
类模板名<实例化的类型> 实例化类对象名;
//Date d1;
类模板名字不是真正的类,实例化的结果才是真正的类。
类模板使用案例
template<class T>
class Vector
{
private:T* _pData;size_t _size;size_t _capacity;public:Vector(size_t capacity = 10):_pData(new T[capacity]),_size(0),_capacity(capacity){}~Vector();
};template <class T>
Vector<T>::~Vector()
{if (_pData)delete[] _pData;_size = 0;_capacity = 0;
}int main()
{Vector<int> S1;//Vector类名 int参数类型
}