文章目录
- 1.函数模板
- 1.1函数模板定义格式
- 1.2关于模板实例化的一些小问题
- 2.类模板
- 2.1 类模板的定义格式
1.函数模板
1.1函数模板定义格式
模板源于C语言一些短板没有解决
#include <stdio.h>
#include<iostream>
using namespace std;
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;
}
int main()
{
int a = 1, b = 2;
Swap(a, b);
double c = 1.11, d = 2.2;
Swap(c, d);
return 0;
}
有一个就交换一个,太麻烦。
C++用泛型编程改进——模板。
无论多少类型模板需要交换,只需要一个模板就可以
template<class T> ,函数列表的参数模板。
template<typename T>
//函数模板
template<class T>//具体类型是什么不知道
void Swap(T& x, T& y)
{
T tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 1, b = 2;
//Swap(a, b);
swap(a,b);//C++库里面有一个,不需要自己写
double c = 1.11, d = 2.2;
//Swap(c, d);
swap(c,d);
return 0;
}
ab和cd调用的不是同一个函数。栈帧也不一样大。
函数模板原理(蓝图,不是函数):并没有减少函数,本质是T实例化是int/double的代码。调用的是模板最后实例化生成的代码。模板的原理是把工作交给了编译器去做。
定义多个模板参数:
template<class X,class Y>
Void Func()
{
}
1.2关于模板实例化的一些小问题
- 隐式实例化:让编译器根据实参推演模板参数的实际类型
template<class T>
T Add(const T& left, const T& right)
{
return left + right;
}
int main()
{
int a1 = 10, a2 = 20;
double d1 = 10.0, d2 = 20.0;
//隐式实例化
//实参传递给形参,自动推演类型。
Add(a1, a2);
Add(d1, d2);//可以编译通过
Add(a1, d1);//编译不能通过,对模板参数T 不明确
//自己强制转化
Add(a1, (int)d1);//强转,此时没有歧义
Add((double)a1, d1);
//显式实例化:在函数名后的<>中指定模板参数的实际类型,自己实例化指定。
//在函数名和函数列表中间加一个模板参数
Add<int>(a1, d1);//传参时隐式类型转换
return 0;
}
- 显式实例化:在函数名后的<>中指定模板参数的实际类型
如果类型不匹配,编译器会尝试进行隐式类型转换,如果无法转换成功编译器将会报错。
//专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}
//通用加法函数
template<class T>
T Add( T left, T right)
{
return left + right;
}
//编译器遇到问题的时候会传特别匹配的那一个
template<class T1,class T2>
{
T Add(T1 left, T2 right)
{
return left + right;
}
}
//可以同时存在
int main()
{
int a=1,b=2;
Add(a,b);//调用第一个,因为调用第一个的成本更低,调用第二个需要先实例化
//如果要求必须用第二个
Add<int>(a,b);
return 0;
}
2.类模板
2.1 类模板的定义格式
template<class T1,class T2,...class Tn>
class 类模板名
{
//类内成员定义
};
//typedef double STDataType;随意改变类型
typedef int STDataType;//可以解决部分问题
class Stack
{
private:
STDataType * _a;
size_t _top;
size_t _capacity;
}
int main()
{
//两份类的代码几乎是一致的
Stack st1;
Stack st2;
//但不能做到一个暂存int,第二个暂存double
return 0;
}
改进:
template<class T>
class Stack
{
public:
Stack(int capacity=4)
{
_a=new T[capacity];
_top=0;
_capacity=capacity;
}
~Stack()
{
delete[] _a;
_capacity=_top=0;//一定要匹配使用
}
private:
T* _a;
size_t _top;
size_t _capacity;
};
int main()
{
Stack<int> st1;//int
Stack<double> st2;//double
vector<int> v;//顺序表,实例化一份数据是int的
//遍历vector
for(size_t i=0;i<v.size();++i)
{
//运算符重载
cout<<v[i]<<" ";
return 0;
}
类模板只能显式实例化