引言:
在C++,我们已经学过了函数重载,这使得同名函数具有多个功能。但是还有一种更省力的方法:采用模板。
本文主要介绍以下内容
1.泛型编程
在将这一部分之前,通过一个故事引入这个知识点。假设这天你干活回家,瘫坐在沙发上,玩起来心爱的古董。当你刚碰到古董的时候,你突然穿越到了古代:三国。诸葛亮刚写了出师表,需要你一晚上誊写出1000份,第二天分发给大家观看,那你该怎么一晚上完成这么繁杂的任务呢?这时候你穿越到了现实世界,带了一个模子回去,模子上刻着字,这样只需要蘸蘸墨水把纸张放上去,便可以高效完成印刷。
可以说泛型编程就是基于这样的思想,我们只需要有一个模板,就可以完成大量的重复操作。而重复操作正是机器擅长的任务,这重复操作就交给了我们的“苦力”--编译器。
这是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;
}
2. 函数模板
函数模板格式:
template<class T>
void Swap(T& t1, T& t2)
{
T tmp = t1;
t1 = t2;
t2 = tmp;
}
int main()
{
int a = 10;
int b = 20;
double c = 1.1;
double d = 2.2;
cout << "before : a = " << a << " b = " << b << endl;
cout << "before : c = " << c << " d = " << d << endl;
Swap(a, b);
Swap(c, d);
cout << "after : a = " << a << " b = " << b << endl;
cout << "after : c = " << c << " d = " << d << endl;
return 0;
}
这是模板函数的使用,可以正常使用!
需要注意的是:这两个Swap调用的是不同的函数!
a c是不同的类型,因此无法对模板的使用。如果我们对c进行强转成int之后,在Swap函数内部进行引用的时候,发生了权限的放大。
// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}
// 通用加法函数
template<class T>
T Add(T left, T right)
{
return left + right;
}
void Test()
{
Add(1, 2); // 与非模板函数匹配,编译器不需要特化
Add<int>(1, 2); // 调用编译器特化的Add版本
}
2.对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板。
// 专门处理int的加法函数
int Add(int left, int right)
{
return left + right;
}
// 通用加法函数
template<class T1, class T2>
T1 Add(T1 left, T2 right) //注意返回类型是T1
{
return left + right;
}
void Test()
{
Add(1, 2); // 与非函数模板类型完全匹配,不需要函数模板实例化
Add(1, 2.0); // 模板函数可以生成更加匹配的版本,编译器根据实参生成更加匹配的Add函
数
}
3.类模板
template<class T> //存储的数据类型是T
class Stack
{
public:
Stack(int capcaity = 4)
:_capacity(capcaity)
, _top(0)
,_array(nullptr)
{
_array = new T[_capacity]; //开辟T类型的数组
}
void Push(const T& x) //插入T类型的数据。普通函数别忘了写返回类型!
{
_array[_top] = x;
_top++;
//容量_capacity不需要++
}
~Stack()
{
delete[] _array;
_array = nullptr;
}
private:
T* _array; //类型是T
int _top;
int _capacity;
};