【C++】模板基础概念
模板初阶
- 之前我们使用函数重载完成交换函数,但是是有缺点的:函数重载仅仅是类型不同,每次有新类型出现时,就需要用户自己增加对应代码,代码复用率低;代码的可维护性低,一个出错可能代表着所有重载均出错
- 因此C++中允许存在一个模具,通过填充不同类型,来生成对应类型的代码
- 泛型编程:编写与类型无关的通用代码,是代码复用的一种手段
- 模板是泛型编程的基础,模板分为函数模板和类模板
函数模板
概念
- 函数模板代表一个函数家族,该函数模板与类型无关,在使用时根据实参类型产生特定类型版本
- 在编译器编译阶段,对于模板函数的使用,编译器会根据传入的实参类型来推演生成对应类型的函数
格式
template<typename T1,typename T2…typename T3>
函数返回值 函数名(参数列表)
{
}
(注意:typename是用来定义模板参数的关键字,也可以使用class)
template<typenameT>voidSwap(T&a,T&b){T tmp=a;a=b;b=tmp;}实例化
隐式实例化:让编译器根据实参推演模板参数并生成对应类型函数
template<typenameT>TAdd(constT&a,constT&b){returna+b;}intmain(){inta=10;intb=20;Add(a,b);doublec=10.1;doubled=20.2;Add(c,d);//Add(a,c);不行//1.强制类型转换Add(a,(int)c);//2.显式实例化return0;}显式实例化:在函数名后加<>,在<>中指定模板参数的类型
//2.显式实例化Add<int>(a,c);- 如果类型不匹配,编译器会进行隐式类型转换,如果无法转换,就会编译报错
参数匹配原则
- 一个非模板函数可以和一个同名的模板函数同时存在
- 对于非模板函数可以和一个同名的模板函数,如果其他条件都相同,调用函数时会优先调用非模板函数,不会用模板来生成
类模板
格式
template<class T1,classT2…class Tn>
class 类名
{
//类内成员
};
实例化
#include<iostream>usingnamespacestd;template<classT>classStack{public:Stack(intn=4):_a(newT[n]),_size(0),_capacity(n){}~Stack(){delete[]_a;_size=0;_capacity=0;}voidPush(constT&x);private:T*_a;size_t _size;size_t _capacity;};template<classT>voidStack<T>::Push(constT&x){if(_capacity==_size){T*tmp=newT[_capacity*2];memcpy(tmp,_a,_capacity);delete[]_a;_a=tmp;_capacity*=2;}_a[_size++]=x;}intmain(){//类模板都是显式实例化Stack<int>st1;Stack<double>st2;st1.Push(1);st1.Push(2);st1.Push(3);st1.Push(4);return0;}