C++:函数模板详解
一、函数模板
#include <iostream>
using namespace std;
// 利用模板实现通用交换函数
// T代表通用的数据类型,告诉编译器下面紧跟着的函数出现T不要报错。
template <class T>
void userSwap(T& var01, T& var02)
{
T tmp = var01;
var01 = var02;
var02 = tmp;
}
/*
模板函数调用方式:
1、自动类型推导:实参列表中,T对应数据类型须一致;
2、显式指定T实参类型
*/
int main()
{
int a = 100;
int b = 200;
// 1、自动类型推导:实参列表中,T对应数据类型须一致;
userSwap(a, b); // 实参a、b均为int型数据,函数可自行推导出T为int型数据类型。
cout<<"a = "<<a<<endl; // a = 200
cout<<"b = "<<b<<endl; // b = 100
float c = 1.414;
float d = 1.732;
// 2、显式指定类型
userSwap<float>(c, d); // 显式指定T为float数据类型,此时实参c、d亦须是float数据类型
cout<<"c = "<<c<<endl; // c = 1.732
cout<<"d = "<<d<<endl; // d = 1.414
return 0;
}
二、模板不能单独使用,须指定T才可以使用。
#include <iostream>
using namespace std;
template <class T>
void func(){}
int main()
{
// func(); // 模板不能单独使用,须指定T才可以使用。
func<int>(); // 指定T的类型为int,可以正常调用
return 0;
}
三、函数模板和普通函数的调用规则
1、若函数模板与普通函数都可以调用,优先调用普通函数
2、若要强制调用函数模板,可使用空模板函数列表
3、函数模板可发生函数重载
4、若函数模板可产生更好的匹配,则优先调用函数模板
#include <iostream>
#include <string>
using namespace std;
template <class TYPE>
void userPrint(TYPE var01, TYPE var02)
{
cout<<"函数userPrint(TYPE var01, TYPE var02)调用"<<endl;
}
// 模板函数发生重载
template <class TYPE>
void userPrint(TYPE var01, TYPE var02, TYPE var03)
{
cout<<"函数userPrint(TYPE var01, TYPE var02, TYPE var03)调用"<<endl;
}
void userPrint(int var01, int var02)
{
cout<<"普通函数userPrint(int var01, int var02)调用"<<endl;
}
int main()
{
int a = 10;
int b = 20;
// a、若函数模板与普通函数都可以调用,优先调用普通函数
userPrint(a, b); // 调用普通函数userPrint(int var01, int var02)
// b、若要强制调用函数模板,可使用空模板函数列表
userPrint<>(a, b); // 调用函数模板userPrint(TYPE var01, TYPE var02)
// c、函数模板可发生函数重载
userPrint(a, b, 10); // 调用函数模板userPrint(TYPE var01, TYPE var02, TYPE var03)
// d、若函数模板可产生更好的匹配,则优先调用函数模板
char c = 'c';
char d = 'd';
userPrint(c, d); // 调用函数模板userPrint(TYPE var01, TYPE var02)
return 0;
}
四、函数模板实现机制
1、编译器并非将函数模板处理成可处理任何类型数据的函数;
2、函数模板通过具体的数据类型产生不同的函数,新生成的函数称为模板函数;
3、编译器会对函数模板进行两次编译。声明时对模板自身代码进行一次编译;在调用时对参数替换后的代码再进行一次编译。
五、函数模板的局限性
1、函数模板并不能对任意的数据类型进行操作(如自定义数据类型);
2、可利用具体化技术,实现对自定义数据类型提供特殊模板。template<> bool myCompare(const Person& a, const Person& b)
#include <iostream>
#include <string>
using namespace std;
class Person
{
public:
string name;
int age;
public:
explicit Person(string name, int age)
{
this->name = name;
this->age = age;
}
};
// 不能对自定义的数据类型数据进行操作
template <class TYPE>
bool myCompare(const TYPE& a, const TYPE& b)
{
return a == b;
}
// 利用具体化技术,实现对自定义数据类型提供特殊模板。
template<> bool myCompare(const Person& a, const Person& b)
{
return (a.name == b.name && a.age == b.age);
}
int main()
{
int a = 10;
int b = 20;
if(myCompare(a, b))
{
cout<<"a == b"<<endl;
}
else{
cout<<"a != b"<<endl;
}
Person p1("Lisi", 20);
Person p2("Lisi", 20);
if(myCompare(p1, p2))
{
cout<<"p1 == p2"<<endl;
}
else{
cout<<"p1 != p2"<<endl;
}
return 0;
}