导航
1.函数模板及注意事项
2.用模板写个排序函数
3.普通函数与函数模板的区别
4.普通函数与函数模板的调用
5.模板的局限性
———————————————————————————————————
1.函数模板
语法:template< typename T>
typename也可以用class
其中T为通用类型,下面看两个例子
例1:
#include <iostream>
using namespace std;
//交换两个整型函数
void swapint(int &a,int &b)
{
int temp = a;
a = b;
b = temp;
}
//交换两个浮点型函数
void swapDouble(double &a,double &b)
{
double temp = a;
a = b;
b = temp;
}
//要写两个函数再调用
void test01()
{
int a = 10,b = 20;
double c = 1.1,d = 2.2;
swapint(a,b);
swapDouble(c,d);
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
cout<<"d = "<<d<<endl;
}
int main()
{
test01();
system("pause");
return 0;
}
为将两个不同类型的值互换我们要写两个函数,若string类型互换呢,就又要写一个函数,这时候我们就可以用到模板
例2:
#include <iostream>
using namespace std;
//函数模板
template<typename T>
void swapT(T &a,T &b)
{
T temp = a;
a = b;
b = temp;
}
void test02()
{
int a = 10,b = 20;
double c = 1.1,d = 2.2;
//1.自动类型推导
swapT(a,b);
//2.显示指定类型
swapT<double>(c,d);
cout<<"a = "<<a<<endl;
cout<<"b = "<<b<<endl;
cout<<"c = "<<c<<endl;
cout<<"d = "<<d<<endl;
}
int main()
{
test02();
system("pause");
return 0;
}
这里我们写一个模板套用即可,模板套用有两种方法
1.自动类型推导——(swap(a,b))
2.显示指定类型——(swap< int >(a,b))
注意事项
1.自动推导类型,必须推导出一致的数据类型,才可以使用
2.模板必须确定T的数据类型,才可以使用
例1:(注意1)
#include <iostream>
using namespace std;
//函数模板
template<typename T>
void swapT(T &a,T &b)
{
T temp = a;
a = b;
b = temp;
}
//注意事项
void test()
{
int a = 10;
int b = 20;
char c = 'a';
swapT(a,b); //正确
//swapT(a,c); //错误
}
int main()
{
test();
system("pause");
return 0;
}
例2:(注意2)
#include <iostream>
using namespace std;
//函数模板
template<typename T>
void func()
{
cout<<"func()调用"<<endl;
}
//注意事项
void test()
{
func<void>(); //这里必须加数据类型,不然无法调用
}
int main()
{
test();
system("pause");
return 0;
}
———————————————————————————————————
2.利用模板写排序函数
#include <iostream>
using namespace std;
//对不同数据类型数组进行排序
//从大到小,算法为选择排序
//类型char型,int型
template<class T>
//交换数值模板
void myswap(T &a,T &b)
{
T temp = a;
a = b;
b = temp;
}
//排序算法模板
template<class T>
void mysort(T arr[],int len)
{
for(int i=0;i<len;i++)
{
int max = i;
for(int j=i+1;j<len;j++)
{
if(arr[j]>arr[max])
{
max = j;
}
}
if(max != i)
{
//交换max与i下标
myswap(arr[i],arr[max]);
}
}
}
//提供打印数组模板
template<class T>
void myprintArr(T arr[],int len)
{
for(int i=0;i<len;i++)
{
cout<<arr[i]<<" ";
}
}
void test01()
{
//测试char数组
char charArr[] = "badcfe";
int len = sizeof(charArr)/sizeof(char);
mysort(charArr,len);
myprintArr(charArr,len);
}
void test02()
{
//测试int数组
int intArr[] = {7,2,5,4,3,1};
int len = sizeof(intArr)/sizeof(int);
mysort(intArr,len);
myprintArr(intArr,len);
}
int main()
{
test02();
system("pause");
return 0;
}
利用模板写会省力一些
———————————————————————————————————
3.普通函数与函数模板的区别
1.普通函数调用可以发生隐式类型转换
2.函数模板用自动类型推导,不可以发生隐式类型转换
3.函数模板用显示指定类型,可以发生隐式类型转换
例:
#include <iostream>
using namespace std;
//普通函数
int func(int a,int b)
{
return a+b;
}
//调用模板
template<class T>
T fun(T a, T b)
{
return a+b;
}
void test02()
{
int a =10,b =20;
char c = 'a';
//1.调用普通函数 可以会发生隐式类型转换
cout<<func(a,b)<<endl;
cout<<func(a,c)<<endl;
//2.用函数模板自动类型推导,不发生隐式类型转换
cout<<fun(a,b)<<endl;
//3.函数模板用显示指定类型,可以发生隐式转换
cout<<fun<int>(a,c)<<endl; //这里要提供指定类型
}
int main()
{
test02();
system("pause");
return 0;
}
———————————————————————————————————
4.普通函数与函数模板的调用规则
1.如果函数模板与普通函数都可以调用,优先调用普通函数
2.可以通过空模板参数列表,强制调用 函数模板
3.函数模板也可以重载
4.如果函数模板可以产生更好的匹配,有限调用函数模板
调用规则1
#include <iostream>
using namespace std;
//普通函数
void myprint(int &a,int &b)
{
cout<<"调用普通函数"<<endl;
}
//函数模板
template<class T>
void myprint(T &a,T &b)
{
cout<<"函数模板调用"<<endl;
}
void test()
{
int a=10,b=20;
myprint(a,b);
}
int main()
{
test();
system("pause");
return 0;
}
结果是先调用普通函数
调用规则2
#include <iostream>
using namespace std;
//普通函数
void myprint(int &a,int &b);
//{
// cout<<"调用普通函数"<<endl;
//}
//函数模板
template<class T>
void myprint(T &a,T &b)
{
cout<<"函数模板调用"<<endl;
}
void test()
{
int a=10,b=20;
myprint<>(a,b); //使用空模板参数列表强制调用
}
int main()
{
test();
system("pause");
return 0;
}
调用规则3
若函数模板发生重载,其中调用参数不同即可
调用规则4
#include <iostream>
using namespace std;
//普通函数
void myprint(int a,int b)
{
cout<<"调用普通函数"<<endl;
}
//函数模板
template<class T>
void myprint(T a,T b)
{
cout<<"函数模板调用"<<endl;
}
void test()
{
char a = 'a',b = 'c';
myprint(a,b);
}
int main()
{
test();
system("pause");
return 0;
}
这里会调用函数模板
———————————————————————————————————
5.模板的局限性
若只传入一些普通类型的单个数据,是可以的,若传入数组或者类,就要使用具体化的方法实现
例:
#include <iostream>
using namespace std;
#include <string>
//写一个类
class Person
{
public:
Person(string name,int age)
{
this->name = name;
this->age = age;
}
string name;
int age;
};
//模板 用于单个普通的类型,数组或者自定义就不行,应该用具体方法实现
template<class T>
bool compare(T a,T b)
{
if(a==b)
{
return true;
}
else
{
return false;
}
}
//写一个person类的模板,里面传入的也要改为对应的类型
template<> bool compare(Person p1,Person p2)
{
if(p1.name == p2.name && p1.age == p2.age)
{
return true;
}
else
{
return false;
}
}
void test()
{
int a=10,b =10;
bool ret = compare(a,b);
//测试普通的类型
if(ret)
{
cout<<"a == b"<<endl;
}
else
{
cout<<"a != b"<<endl;
}
//测试Person类
Person p1("小明",12);
Person p2("小明",12);
bool ret1 = compare(p1,p2);
if(ret1)
{
cout<<"p1 == p2"<<endl;
}
else
{
cout<<"p1 != p2"<<endl;
}
}
int main()
{
test();
system("pause");
return 0;
}