两个数求和:
1)C语言泛型 void* [ )--------------半开半闭,易越界
2)函数重载 ---------------------------类型有限制
3)宏-------------------------------------不安全
4)C++泛型----------------------适宜
c++泛型用模板来实现、
1.函数模板:
自己定义的代码叫函数模板
template<typename T>
T Sum(T a, T b)
{
cout << typeid(T).name() << endl;
return a + b;
}
模板编译:
定义点:编译模板的头部
调用点编译:编译模板函数
2.模板函数:
假如实参传入为int ,int替换成T,实例化后生成的函数叫做模板函数。替换属于 typedef的替换
int Sum(int a, int b)
{
cout << typeid(int).name() << endl;
return a + b;
}
3.模板的实例化:
实参类型替换形参类型的过程叫做模板的实例化。
4.模板的实参推演:
没有传入实参类型,推演其类型,编译器通过()中的值与模板中形参进行匹配,编译器可以辨识数值为什么类型。
模板实参推演限制:
1)不能让编译器产生二义性
2)有实参
template<typename T>
T Get()
{
T tmp;
return tmp;
}
这个没有实参,就有错误
参考代码:
#include<iostream>
using namespace std;
/*
<>模板类型参数列表 typenmae说明后面是一个类型
*/
template<typename T>//形参虚拟的类型
T Sum(T a, T b)//两个数求和
{
cout << typeid(T).name() << endl;
return a + b;
}
int main()
{
Sum<int>(10, 20);// <>模板实参列表 实参是具体的类型,把类型参数化了
Sum<double>(10.1, 20.1);
Sum<char>('a', 'b');
Sum(10, 20);//没有传入实参类型,推演其类型,编译器通过()中的值与模板中形参进行匹配
//Sum(10.1,20); 报错,产生二义性
return 0;
}
5.模板的非类型参数
1)int len = sizeof(arr) / sizeof(arr[0]);//报错
修改:const int len = sizeof(arr)/ sizeof (arr[0]);
2)template<typename T,float LEN> //LEN 非类型参数
模板的非类型参数特点:
1)常量
2)内置类型中不能用float,double
代码:
#include<iostream>
using namespace std;
template<typename T>//冒泡排序
void Sort1(T *arr,int len)//一个虚假类型,一个自定义类型
{
T temp;
for (int i = 0; i < len-1; i++)
{
for (int j = 0; j < len - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
template<typename T,int LEN> // T 类型参数 LEN 非类型参数
void Sort2(T *arr)
{
T temp;
for (int i = 0; i < LEN - 1; i++)
{
for (int j = 0; j < LEN - i - 1; j++)
{
if (arr[j] > arr[j + 1])
{
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
template<typename T>
void Show(T *arr, int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << " ";
}
cout << endl;
}
int main()
{
int arr[] = { 10,9,87,6,45,4,6,8,5,32 };
//int len = sizeof(arr) / sizeof(arr[0]);
const int len = sizeof(arr)/ sizeof (arr[0]);
Show<int>(arr, len);
Sort1<int>(arr, len);//Sort(arr,len)
Show<int>(arr, len);
Sort2<int,len>(arr);
Show<int>(arr, len);
return 0;
}
6.模板的特例化
完全特例化
函数模板支持完全特例化
部分特例化
类模板不仅支持完全特例化,也支持部分特例化
函数模板不能满足某些需求,需单独处理
#include<iostream>
using namespace std;
template<typename T>
bool Compare(T a, T b)
{
cout << "template<typename T>"<<endl;
return a > b;
}
template<> //此时不是模板,已进化为函数,会编译
bool Compare<char*>(char* a, char *b)// Compare<char*>构成函数名
{
cout << "template<>"<<endl;
return strcmp(a, b) > 0;
}
int main()
{
Compare<int>(10, 20);
Compare<double>(10.1, 20.1);
Compare<char*>("hello", "world");
return 0;
}
特例化注意事项:
错误解释:
上面:const 修饰 a,b ,修饰 T类型 T类型 是 char*
下面:cnnst 修饰 *a , *b 修饰 char类型
原因:特例化实现的逻辑和模板实例化实现的逻辑不一样
修改:
7.模板的重载
#include<iostream>
using namespace std;
//模板函数
template<typename T>
bool Compare(const T a,const T b)
{
cout << "template<typename T>"<<endl;
return a > b;
}
//普通函数
bool Compare(char *a, char *b)
{
cout << "Compare()" << endl;
return strcmp(a, b) > 0;
}
//特例化
template<>
bool Compare<char*>(char* a,char *b)
{
cout << "template<>"<<endl;
return strcmp(a, b) > 0;
}
int main()
{
Compare<int>(10, 20);
Compare<double>(10.1, 20.1);
Compare<char*>("hello", "world");//调用特例化
Compare("hello", "world");//调用实例化
return 0;
}
优先级:普通函数>特例化>函数模板