泛型编程
泛型编程,编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
- 可以理解为活字印刷术类似的方式。
函数模板
函数模板概念
函数模板,代表一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
解决函数作用相同,但是参数类型不同,得写好几个参数不同但函数功能相同的代码,函数模板就是解决这个问题。
本来应该我们做的重复的事情交给了编译器。
函数模板语法
cpp
template<typename T1,typename T2,...,typename Tn>
返回类型 函数名(参数列表){}
- typename是定义模板参数 的关键字
- 也可以使用class,但不能是struct
函数模板使用案例
cpp
#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=3
double d = 2.63, e = 9.35;
Swap(d, e);
cout << "d=" << d << " " << "e=" << e << endl;//d=9.35 e=2.63
return 0;
}
函数模板原理
- 函数模板,本身并不是函数;
- 是编译器产生特定具体类型函数的模具;
- 在编译器编译阶段,编译器 根据传入的实参类型 来推演生成对应类型的函数。
- 例如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码。
函数模板实例化
用不同类型的参数使用函数模板时 ,称为函数模板的实例化 。模板参数实例化分为:隐式实例化和显示实例化。
隐式实例化
隐式实例化 ,让编译器自己根据实参推演模板参数的实际类型。
cpp
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; //30
cout << 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.7
cout << Add(a1, (int)d1) << endl;//56.7
return 0;
}
显示实例化
显示实例化 ,在函数名后的**<>中指定** 模板参数的实际类型。
cpp
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;//20
return 0;
}
模板参数的匹配规则
- 一个非模板函数可以和一个同名模板函数同时存在。
非模板函数与同名模板函数同时存在时:
- 调用函数与非模板函数匹配时,编译器不需要推演特化;
- 有显示实例化,编译器进行函数模板推演;
- 优先调用非模板函数;
- 模板函数不允许自动类型转换,但普通函数可以进行自动类型转化。
类模板
将类中的成员变量或者成员函数的参数数据类型进行模板化。
类模板名字不是真正的类,实例化的结果才是真正的类。
类模板语法
- 类模板中函数放在类外进行定义时,需要加模板参数列表。
cpp
template<class T1,class T2,...,class Tn>
class 类模板名
{
//类成员
};
//类模板函数在类外定义,加模板参数列表
template<class T1,class T2,...,class Tn>
类模板名<T1/T2/.../Tn>::类模板成员函数名()
{
函数功能
}
int main()
{
类模板名<实例化类型> 类对象实例化名字;//Date d;
}
类模板实例化
cpp
类模板名<实例化的类型> 实例化类对象名;
//Date d1;
类模板名字不是真正的类,实例化的结果才是真正的类。
类模板使用案例
cpp
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参数类型
}