导航
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; }