【轻敲stl的大门】函数模板和类模板
文章目录
- 泛型编程---模板
- 函数模板
- 类模板
- 最后我在这里祝各位佬10.24程序员节快乐呀~~
(可以不看)背景
某一天你的老板叫你把几个数据交换一下,其中有整数、小数,名字等等。于是你开始码字,不一会功夫就做完了一个整形的和浮点型交换函数。
于是你想把代码实现给老板看看反向有没有问题,老板看完后咔咔给你几个大嘴巴子说:“这个太麻烦拉,我还要用眼睛去看小数和整数来区分的使用函数接口,那如果是小数和和整数,名字交换呢?那是不是又得加一个接口?那我还需要你干嘛?我自己去excel表上搞算了!
这时候你慌了,你被老板批评得找不着北了。这时候就需要函数模板又或者是类模板上场拉!
泛型编程—模板
泛型编程:编写与类型无关的通用代码,是代码复用的一种手段。模板是泛型编程的基础。
函数模板
语法:template< typename T>
{template-模板关键字关键字;typename-(或者是class但不能用struct)定义模板参数关键字 ;
T:自定义模板的名字}
1.函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。
2.它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器。(编译器化身打工人,我则是懒狗)
3.在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。
4.用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例化
隐式实例化:让编译器根据实参推演模板参数的实际类型
template<typename S>
void swap(S& x, S& y)
{
S tmp = x;
x = y;
y = tmp;
}
int main()
{
int a = 5, b = 7;
double c = 3.40, d = 5.20;
swap(a, b);
swap(c, d);
//swap(a, d);---错误实例
//为什么不能让int类型和double类型互换?推演模板实例化在调用参数之前,这时候推演模板实例化模板参数(S)只有一个,出现两个参数类型编译器不知道要推演哪一个则会报错;这时候还轮不到调用参数的隐式转化(整形提升-数据截断等等);
// 就算是发生参数的隐式类型转化,参数a会先拷贝出一份临时变量然后再传给函数进行调用参数x-临时变量具有常性,那么参数x要加const,但参数x引用加const又怎么交换呢?
return 0;
}
那么当出现两种参数类型时,我们应该怎么做呢?
这里有三种解决方案。
1.强制转化(显示类型转化)
2.显示实例化
语法:函数< 要显示实例化的参数类型>(参数1,参数2…)
3.多个参数模板
另:函数模板和相同函数可以同时存在吗?可以!
但是我们通过调试发现当出现相同类型的函数和函数模板时编译器会优先选择函数!(得出结论函数也是懒狗)
而且调用模板的地址是相同的!看具体满足的需求来优先调用函数还是函数模板!
类模板
类模板一般显示实例化
1.类模板自定义格式:template<class T1, class T2, …, class Tn>
2.类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类。
比如:Stack-类名;Stack< int >-类型
这里贴一份代码强化理解
template<typename T>
class Stack
{
public:
Stack(int capacity = 4)//构造函数
{
cout << "Stack(int capacity = )" << capacity << endl;
_a = (T*)malloc(sizeof(T) * capacity);
if (_a == nullptr)
{
perror("malloc fail");
exit(-1);
}
_top = 0;
_capacity = capacity;
}
~Stack()//析构函数
{
cout << "~Stack()" << endl;
free(_a);
_a = nullptr;
_top = _capacity = 0;
}
void Push(T x)
{
// ....
// 扩容
_a[_top++] = x;
}
private:
T* _a;
int _top;
int _capacity;
};