1 泛型编程
如何将Swap实现乘成一个通用的交换函数
void Swap(int& left, int& right)
{int temp = left;left = right;right = temp;
}void Swap(double& left, double& right)
{double temp = left;left = right;right = temp;
}void Swap(char& left, char& right)
{char temp = left;left = right;right = temp;
}
可以看出三个Swap函数相似度极大,而且俩传入参数类型相同,这时候可以利用模板关键字template就能将传入类型抽象出来通用。
template <class T>
void Swap(T& left, T& right)
{T temp = left;left = right;right = temp;
}
将多个类似只是类型不同的函数都可以利用模板将其通用化,类型不同可以表现在传入参数类型不同,返回值类型不同等。
模板分类
1 函数模板
函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
template <class T>
void Swap(T& left, T& right)
{T temp = left;left = right;right = temp;
}
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。简单说就是编译预处理的时候就会将调用的函数模板转换出调用类型的函数代码,意思就是编译器会自动为我们生成所需的调用函数的代码,模板本质上是替换。
函数模板的实例化
用不同类型的参数使用函数模板时,称为函数模板的实例化。
模板参数实例化分为:隐式实例化和显式实例化。
隐式实例化:编译器自动推导T为什么类型
显式实例化:用<>指定T的类型
模板参数匹配
同名的模板函数和非模板函数可以同时存在,而且该模板函数也可以实例化为这个非模板函数。
但调用的时候有所区别。
3 类模板
类模板定义格式
template<class T1, class T2, ..., class Tn>
class 类模板名
{
// 类内成员定义
};
模拟实现vecotor部分功能
#include <iostream>
#include <assert.h>
#include <string>
using namespace std;
template <class T>
class vector
{
public: //不能省 省了就会报错。vector():_a(nullptr),_size(0),_capacity(0){}~vector(){delete[] _a;_a = nullptr;_size = 0;_capacity = 0;}size_t size(){return _size;}T& operator[](size_t i) //传值返回是临时拷贝,属于常量不可修改,如果需要对返回值进行修改需要传引用{assert(i < _size);return _a[i];}void Push_Back(const T &x);void Pop_Back();
private:T* _a;size_t _size;size_t _capacity;
};
template<class T>
void vector<T>::Push_Back(const T& x)
{if (_size == _capacity){size_t newcapacity = (_capacity == 0 ? 2 : _capacity * 2);T* temp = new T[newcapacity];if (_a){memcpy(temp, _a, sizeof(T) * _size);delete[] _a;}_a = temp;_capacity = newcapacity;}_a[_size] = x;_size++;
}
template <class T>
void vector<T>::Pop_Back()
{assert(_size > 0);_size--;
}int main()
{vector<int> v;v.Push_Back(1);v.Push_Back(2);v.Push_Back(3);for (size_t i = 0; i < v.size(); i++){v[i] *= 2;}for (size_t i = 0; i < v.size(); i++){cout << v[i];}return 0;
}
类模板实例化
类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
// Vector类名,Vector<int>才是类型
Vector<int> s1;
Vector<double> s2;