一.函数模板
我们可以定义一个函数模板(function template),而不是为每个类型都定义一个函数。一个函数模板就是一个蓝图,可用来生成针对特定类型的函数。
例如用于比较两个数字的大小compare()函数的模板如下:
template <typename T>
int compare(const T &v1,const T &v2)
{
if(v1 > v2) return 1;
if(v2 > v1) return -1;
return 0;
}
二.函数模板语法
函数模板格式如下:
template<typename T,typename T2,…>
函数返回类型 函数名(模板形参表)
{
函数体
}
说明:
(1)template : 声明创建模板;
(2)typename : 类型名称,表示后面跟的是类型名,可以用class替代typename;
(3)T : 通用类型名,一般使用大写 T;
(4)< >里面的类型参数可以有一个或多个,每个模板形参前必须有关键字 class或typename,多个类型参数之间用逗号分隔;
使用举例:
#include <iostream>
#include <string>
using namespace std;
template<typename T>
int compare(const T& v1, const T& v2)
{
if (v1 > v2) return 1;
if (v2 > v1) return -1;
return 0;
}
int main()
{
int a = 10;
int b = 20;
double c = 12.4;
double d = 8.6;
cout << compare(a, b) << endl;
cout << compare(c, d) << endl;
return 0;
}
1.1.1 实例化函数模板
当我们调用一个函数模板时,编译器用实参来为我们推断模板类型。例如在下面的调用中:
template<typename T>
int compare(const T& v1, const T& v2)
{
if (v1 > v2) return 1;
if (v2 > v1) return -1;
return 0;
}
int a = 10;int b = 20;
cout << compare(a, b) << endl; //a,b是int,推断 T是int
compare实参类型是int,编译器会推断出模板T为int。
在如下的代码中:
double c = 12.4;
double d = 8.6;
cout << compare(c, d) << endl;//c,d为double,推断T是double
compare实参类型是double,编译器会推断出模板T为double。
函数模板告诉编译器如何定义函数。当调用实参是 int时,编译器将按函数模板创建这样的函数,并用int代替T;当调用实参是double时,编译器将按函数模板创建这样的函数,并用double代替T。下面是vs2022的一段反汇编,仅供参考。
1.1.2 模板类型
模板类型:在上例中 T就是模板类型。
一般来说,我们可以将模板类型看作类型说明符,就像内置类型一样使用。可以用来指定返回值类型,函数参数类型,以及在函数体内用于变量声明。
template<typename T>
T fun(T* p) //T作为返回值,T做形参
{
T tmp = *p; //T定义变量
//...
return tmp+1;
}
int main()
{
int a = 10;
cout << fun(&a) << endl;
return 0;
}
说明:
1.模板类型前必须使用关键字class或typename;
template <typename T,U>//错误,U前面必须加class或typename
T fun(const T&v1,const U&v2);
在模板参数列表中,这class和typename两个关键字的含义相同,可以互换。一个模板参数列表中可以同时使用这两个关键字
template <typename T,class U>//正确,class和typename可以互换
T fun(const T&v1,const U&v2);
建议使用typename,这个关键字更直观。但typename是后引入C++的,有些程序还在使用class。
1.1.3 编写要求
通常,我们将类声明和函数声明放在头文件中,函数定义和类成员函数的定义放在源文件中。
模板则不同:为了生成一个实例化版本,编译器需要掌握函数模板或类模板成员函数的定义。因此,模板声明也和定义都放在头文件中(有时不写文件后缀名)。
编写模板时,代码不能是针对特定类型的,但模板代码通常对其所使用的类型有一些假设。例如,在compare 函数中的代码就假定类型定义了 > 运算符。
if (v1 > v2) return 1; //T类型必须支持 > 运算符
if (v2 > v1) return -1;//T类型必须支持 > 运算符
1.1.4 函数模板实参推断
●函数模板调用时,如果不能从实参推断出模板实参,就必须显式指定它
template<typename T>
T Max(T a, T b)
{
cout << "T Max(T,T)" << endl;
return a > b ? a : b;
}
int main()
{
int a = Max(10, 20);
//int b = Max(200, 'a');//错误,不能通过实参推断出模板实参
int c = Max<int>(200,'a');//可以,显式指定类型为int
int d = Max(200,(int)'a');//可以,显式类型转换,可以通过实参推断
return 0;
}
1.1.5 函数模板重载
可以定义多个同名的函数模板,甚至同名的函数模板和普通函数可以同时存在。例如:
#include <iostream>
using namespace std;
int Max(int a, int b)
{
cout << "int max(int,int)" << endl;
return a > b ? a : b;
}
template<typename T>
T Max(T a, T b)
{
cout << "T max(T,T)" << endl;
return a > b ? a : b;
}
template<typename T>
void Max(T a, T b, T c)
{
cout << "T max(T,T,T)" << endl;
}
int main()
{
int a = Max(10, 20);//普通函数
int b = Max('a','A');//函数模板
Max(10,20,30);//函数模板
return 0;
}
本篇完!
标签:return,函数,v1,--,v2,C++,STL,int,模板 From: https://blog.csdn.net/m0_75266675/article/details/136885747