最近在学习C++的过程中,发现函数模板的功能非常多,并且能减少许多工作量,减少重复代码,在这里对学习过程中的内容和经验进行一下总结。
1.函数模板的格式:
2.函数模板的调用方式
3.普通函数与函数模板的区别
4.函数模板的重载
5.函数模板特化
6.函数模板嵌套
7.函数模板的非类型参数
8.总结
template
{函数返回值类型} {函数名} (参数) { }
其中 class 与 typename 的作用一致,都是用来声明一个通用类型,也可叫做虚拟类型;
对于函数模板有两种调用方式,第一种是显式调用方式,第二种则是隐式调用方式。
第一种:显式调用格式
{函数名}<实际类型1,实际类型2>(参数列表);
例:
#include
using namespace std;
template
void fun(T temp)
{
cout << temp << endl;
}
int main()
{
fun(30);
return 0;
}
第二种:隐式调用格式
{函数名}(参数列表);
例:
#include
using namespace std;
template
void fun(T temp)
{
cout << temp << endl;
}
int main()
{
fun(30);
return 0;
}
但对于隐式调用来说有一个问题不能忽视,那就是如果有一个与函数模板同名的一个普通函数重载,则在使用隐式调用时会优先调用普通函数而非调用模板函数。
例:
#include
using namespace std;
template
void fun(T temp)
{
cout << temp << endl;
cout << "此处是模板函数" << endl;
}
void fun(int temp)
{
cout << temp << endl;
cout << "此处是普通函数" << endl;
}
int main()
{
fun(30);
return 0;
}
终端输出结果:
30
此处是普通函数
与普通函数的重载相类似,都是在同一个作用域内函数名相同且参数列表不同。
例:以下是参数顺序不同的重载
#include
using namespace std;
template
void fun(T1 a,T2 b)
{
cout << "这是fun1函数" << endl;
}
template
void fun(T2 a,T1 b)
{
cout << "这是fun2函数" << endl;
}
int main()
{
fun(10,10.0);
fun(10.0,10);
return 0;
}
终端输出结果:
这是fun1函数
这是fun2函数
当函数模板需要处理一些特定的类型,诸如类、数组、结构体等时,无法对这些类型的数据进行处理,为了解决这种局限性,在定义函数模板时,直接确定好类型,这就是特化的函数模板。
如果传入的是自定义类型,并且和特化版本匹配,会优先使用特化版本。
函数模板特化格式:
template<>{函数返回值}{函数名}(类名& 对象){ }
例:
#include
#include
using namespace std;
class person
{
public:
int age;
string name;
public:
person(int age,string name);
~person();
};
person::person(int age,string name)
{
this->age = age;
this->name = name;
}
person::~person()
{
}
template
bool compare(T a,T b)
{
if(a == b)
{
return true;
}
else return false;
}
template<>
bool compare(person a,person b)
{
if(compare(a.age,b.age) && compare(a.name,b.name) )
{
return true;
}
else return false;
}
int main()
{
person a(1,"fff");
person b(1,"fff");
cout << compare(a,b) << endl;
return 0;
}
注意:当使用函数模板特化时,需要在上方定义一个相同函数名的函数模板,否则编译器会报错。或者可以在函数模板的尖括号中加上 class {通用类型名} ,也可以避免编译器报错。
有时为了方便,会直接在函数模板中直接调用另一个函数模板,比如需要使用函数模板比较出2至4种参数的最大值,此时就能使用函数模板嵌套来减少代码量。
例:
#include
using namespace std;
template
T Max(T a,T b)
{
T max = a;
if(max < b)
{
max = b;
}
return max;
}
template
T Max(T a,T b,T c)
{
T max = Max(Max(a,b),c);
return max;
}
template
T Max(T a,T b,T c,T d)
{
T max = Max(Max(a,b,c),d);
return max;
}
int main()
{
cout << "max = " << Max(10,20) << endl;
cout << "max = " << Max(30,2,13) << endl;
cout << "max = " << Max(11,33,24,1) << endl;
return 0;
}
当需要往函数模板中传入一个特定的确定参数但不希望将该参数放在小括号中时,即可通过使用非类型参数实现。
格式:
template
{函数返回值类型}{函数名}(T& {参数名});
例:
#include
using namespace std;
template
void display(T* buf)
{
for (size_t i = 0; i < size; i++)
{
cout << buf[i] << endl;
}
}
int main(int argc, char const *argv[])
{
int num[] = {10,20,11,33,44,11,23};
const int size = sizeof(num)/4;
display(num);
return 0;
}
特别注意:在使用非类型参数时,非类型参数都是常量,在函数中不允许被修改,所以在定义时需要将该参数定义为const类型,否则编译器会报错。
如上,此文仅为本人在C++学习过程中对函数模板的经验总结,对于函数模板还有许多便利的使用场景及方法值得我们去探究。如果有对于函数模板不明白之处的人希望该文能帮到你。