C++提供了函数模板,实际上就是建立一个通用的函数,其函数类型和形参类型不具体指定,用一个虚拟的类型来代表,这个通用函数就成为函数模板,凡是函数体相同的函数都可以用这个模板代替,不必定义多个函数,只需要在模板中定义一次即可,在调用函数时系统会根据实参类型来取代模板中的虚拟类型,从而实现不同函数的功能。
总结:
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
// T代表泛型的数据类型 不能只是写T
// 让编译器看到这句话后面紧跟着的函数里面有 T 不要报错
template<class T>
void mySwap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
// 使用函数模板
void test02()
{
int a = 10;
int b = 20;
mySwap(a, b);
cout << "a = "<< a << endl;
cout << "b = " << b << endl;
}
int main()
{
test02();
return EXIT_SUCCESS;
}
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
// T代表泛型的数据类型 不能只是写T
// 让编译器看到这句话后面紧跟着的函数里面有 T 不要报错
template<class T>
void mySwap(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
// 使用函数模板
void test02()
{
int a = 10;
int b = 20;
// 编译器会根据实参来自动推导数据类型
mySwap(a, b);
/*
编译器在函数模板被调用的时候,进行第二次编译 确定具体数据类型
void mySwap(int &a,int &b)
{
int tmp = a;
a = b;
b = tmp;
*/
cout << "a = "<< a << endl;
cout << "b = " << b << endl;
// 显示的指定类型
mySwap<int>(a, b);//<> 使用参数列表
}
int main()
{
test02();
return EXIT_SUCCESS;
}
如果使用参数列表指定数据类型,那么实参就可以进行隐式转换
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
// T代表泛型的数据类型 不能只是写T
// 让编译器看到这句话后面紧跟着的函数里面有 T 不要报错
template<class T>
T func(T a, T b)
{
return a + b;
}
void test03()
{
int a = 10;
double b = 20.2;
// 指定数据类型 int 这里的double会自动进行数据转换
cout << func<int>(a, b);// 打印30
}
int main()
{
test03();
return EXIT_SUCCESS;
}
可以使用typename定义函数模板
template<typename T>
void func(T a, T b)
{
}
这里使用函数模板编写一个冒泡排序算法,适用于任何类型的数组
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
// T代表泛型的数据类型 不能只是写T
// 让编译器看到这句话后面紧跟着的函数里面有 T 不要报错
template<class T>
void mySort(T arr[], int len)
{
// 冒泡排序
for (int i = 0; i < len; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
T tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
// 使用函数模板 打印数组
template<class T>
void myPrint(T arr[], int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
void test03()
{
// 可以传入任意类型的数组进入函数模板
char arrchar[] = "hello world";
int len = sizeof(arrchar) / sizeof(char);
mySort(arrchar, len);
myPrint(arrchar,len);
int arrInt[] = {1,34,25,36,546,12,11};
len = sizeof(arrInt) / sizeof(int);
mySort(arrInt, len);
myPrint(arrInt, len);
}
int main()
{
test03();
return EXIT_SUCCESS;
}
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
// 普通函数
int myPlus(int a, int b)
{
return a + b;
}
template<class T>
int myPlus2(T a, T b)
{
return a + b;
}
void test()
{
int a = 10;
int b = 20;
char c = 'a';// 转换成int 数据类型 变为97
// 普通函数可以直接进行隐式转换
int d = myPlus(a,c);
cout << d << endl;
// 函数模板不可以直接进行隐式转换
int e = myPlus2<int>(b,c);
cout << e << endl;
}
int main()
{
test();
return EXIT_SUCCESS;
}
函数模板和普通函数可以进行重载
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
// 普通函数
int myPlus(int a, int b)
{
return a + b;
}
template<class T>
int myPlus(T a, T b)
{
return a + b;
}
void test()
{
int a = 10;
int b = 20;
char c = 'a';// 转换成int 数据类型 变为97
// 普通函数可以直接进行隐式转换
int d = myPlus(a,c);
cout << d << endl;
// 函数模板不可以直接进行隐式转换
int e = myPlus<int>(b,c);
cout << e << endl;
}
int main()
{
test();
return EXIT_SUCCESS;
}
但是普通函数和函数模板进行重载的时候,编译器优先使用,普通函数,避免二次编译,所以要使用函数模板,还是需要使用参数列表
函数模板和函数模板之间也可以进行重载
如果函数模板可以产生更好的匹配,那么优先使用函数模板
如果传入的是数组名,那么函数模板中比较函数名的大小就没有意义,因为这里数组名是地址,所以他们比较的是地址。
#define _CRT_SECURE_NO_WARNINGS
#include
using namespace std;
template<class T>
void func(T a, T b)
{
if (a > b)
{
cout << "a > b" << endl;
}
else
{
cout << "a <= b" << endl;
}
}
void test()
{
int arr[20];
int arr2[20];
func(arr,arr2);
}
int main()
{
test();
return EXIT_SUCCESS;
}
总之,编写的模板函数很可能没办法处理某些数据类型,另一方面,有时候通用化是有意义的。模板的重载可以为这些特定的类型提供具体化的模板
#define _CRT_SECURE_NO_WARNINGS
#include
#include
using namespace std;
class Maker
{
public:
Maker(string name,int age)
{
this->name = name;
this->age = age;
}
public:
string name;
int age;
};
template<class T>
void myfunc(T& a, T& b)
{
if (a > b)
{
cout << "a > b" << endl;
}
else
{
cout << "a < b" << endl;
}
}
// 函数模板的具体化 先写函数模板 才能具体化 指定参数列表 然后传入指定参数
template<>void myfunc<Maker>(Maker& a, Maker& b)
{
cout << "函数模板的具体化" << endl;
if (a.age > b.age)
{
cout << "a > b" << endl;
}
else
{
cout << "a < b" << endl;
}
}
void test()
{
Maker a("z",1);
Maker b("a",11);
myfunc(a,b);
}
int main()
{
test();
return EXIT_SUCCESS;
}