函数模板

1、为什么引入函数模板?

考虑下面两个需求:

  • 交换两个整型变量的值的Swap函数:
void Swap(int & x,int & y)
{
	int tmp = x;
	x = y;
	y = tmp;
}
  • 交换两个double型变量的值的Swap函数:
void Swap(double & x,double & y)
{
	double tmp = x;
	x = y;
	y = tmp;
}

上述代码有着明显的重复。考虑一个问题:能否只写一个Swap,就能交换各种类型的变量?(即:提高代码的重用性)

2、解决问题的方案:引入函数模板

(1)定义模板的语法:
template <class 类型参数1,class 类型参数2,......>
返回值类型 模板名 (形参表)
{
	函数体
};

(2)针对上述问题,可以定义函数模板:

template <class T>
void Swap(T & x,T & y)
{
	T tmp = x;
	x = y;
	y = tmp;
}

编译器会在函数调用语句处,自动根据函数模板实参类型生成一个函数。由模板生成的函数被称为模板函数

3、举栗子。

(1)例1,函数模板可以不止有一个类型参数
template <class T1, class T2>
T2 print(T1 arg1, T2 arg2)
{
	cout<< arg1 << " "<< arg2<<endl;
	return arg2;
}
(2)例2,求数组最大元素的MaxElement函数模板
template <class T>
T MaxElement(T a[], int size) //size是数组元素个数
{
	T tmpMax = a[0];
	for( int i = 1;i < size;++i)
	if( tmpMax < a[i] )
	tmpMax = a[i];
	return tmpMax;
}

4、实例化函数模板的两种方式

(1)方式一:通过参数实例化(隐式实例化)

注意:匹配模板函数时,不进行类型自动转换。

template<class T>
T myFunction( T arg1, T arg2){ 
	cout<<arg1<<" "<<arg2<<"\n"; 
	return arg1;
}
void main(){
	myFunction( 5, 7); 		//ok:replace T with int
	myFunction( 5.8, 8.4); 	//ok: replace T with double
	myFunction( 5, 8.4); 	//error,no matching function for callto 'myFunction(int, double)'
}
(2)方式二:不通过参数实例化函数模板(显式实例化)

举栗:

#include <iostream>
using namespace std;
template <class T>
T Inc(T n)
{
	return 1 + n;
}
int main()
{
	cout << Inc<double>(4)/2;
	return 0;
}

考虑:是否支持参数隐式转换?

4、模板重载

函数模板可以重载,只要它们(它们指的是:实例化出来的函数)的形参表或类型参数表不同即可。

template<class T1, class T2>
void print(T1 arg1, T2 arg2) {
	cout<< arg1 << " "<< arg2<<endl;
}
template<class T>
void print(T arg1, T arg2) {
	cout<< arg1 << " "<< arg2<<endl;
}
template<class T,class T2>
void print(T arg1, T arg2) {
	cout<< arg1 << " "<< arg2<<endl;
}

5、函数模板和函数的次序

在有多个函数和函数模板名字相同的情况下,编译器如下处理一
条函数调用语句:

  • 先找参数完全匹配的普通函数(非由模板实例化而得的函数)。
  • 再找参数完全匹配的模板函数。
  • 再找实参数经过自动类型转换后能够匹配的普通函数。
  • 上面的都找不到,则报错。

举栗子:

template <class T>
T Max( T a, T b) {
cout << "TemplateMax" <<endl;
return 0;
}
template <class T,class T2>
T Max( T a, T2 b) {
	cout << "TemplateMax2" <<endl;
	return 0;
}
double Max(double a, double b){
	cout << "MyMax" << endl;
	return 0;
}
int main() {
	int i=4, j=5;
	Max( 1.2,3.4); // 输出MyMax
	Max(i, j); //输出TemplateMax
	Max( 1.2, 3); //输出TemplateMax2
	return 0;
}

6、函数模板示例:Map

#include <iostream>
using namespace std;
template<class T,class Pred>
void Map(T s, T e, T x, Pred op)
{
	for(; s != e; ++s,++x) {
		*x = op(*s);
	}
}
int Cube(int x) {
	return x * x * x; 
}
double Square(double x) {
	 return x * x; 
}

int a[5] = {1,2,3,4,5}, b[5];
double d[5] = { 1.1,2.1,3.1,4.1,5.1} , c[5];
int main() {
	Map(a,a+5,b,Square);
	for(int i = 0;i < 5; ++i) cout << b[i] << ",";
	cout << endl;
	Map(a,a+5,b,Cube);
	for(int i = 0;i < 5; ++i) cout << b[i] << ",";
	cout << endl;
	Map(d,d+5,c,Square);
	for(int i = 0;i < 5; ++i) cout << c[i] << ",";
	cout << endl;
	return 0;
}
/*输出:
1,4,9,16,25,
1,8,27,64,125,
1.21,4.41,9.61,16.81,26.01,
*/

实例化函数解释:

//函数模板
template<class T,class Pred>
void Map(T s, T e, T x, Pred op) {
	for(; s != e; ++s,++x) {
		*x = op(*s);
	}
}
//实例化的模板函数
void main(){
	int a[5] = {1,2,3,4,5}, b[5];
	Map(a,a+5,b,Square); //实例化出以下函数:
}

void Map(int * s, int * e, int * x, double ( *op)(double)) {
	for(; s != e; ++s,++x) {
		*x = op(*s);
	}
}
posted @ 2019-12-12 19:21  江南又一春  阅读(260)  评论(0编辑  收藏  举报