C++模版
模版的概念
1、模版就是建立通用的模具,大大提高复用性
2、模版的特点:
①模版不可以直接使用,它只是一个框架
②模版的通用并不是万能的
函数模版
C++另一种编程思想称为泛式编程,主要利用的技术就是模版
C++提供两种模版机制:函数模版和类模版
函数模版语法
1、函数模版作用:
建立一个通用模版,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表
2、语法:
template<typename T>
函数声明或定义
3、解释:
①template——声明创建模版
②typename——表面其后面的符号是一种数据类型,可以用class代替
③ T——通用的数据类型,名称可以替换,通常为大写字母
4、总结:
①函数模板利用关键字 template
②使用函数模板有两种方式:自动类型推导、显示指定类型
③模板的目的是为了提高复用性,将类型参数仅
//交换两个整形函数
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;
}
//函数模版
template<typename T> //声明一个模版,告诉编译器后面代码中紧跟着的T不要报错,T是一个通用数据类型
void mySwap(T &a,T &b){
T temp = a;
a = b;
b = temp;
}
void test01(){
int a=10;
int b=20;
//swapInt(a,b);
//利用函数模版交换
//两种方式使用函数模版
//1、自动类型推导
mySwap(a,b);
//2、显示指定类型
mySwap<int>(a,b);
cout <<a<<endl;
cout <<b<<endl;
double c=1.1;
double d=2.2;
swapInt(c,d);
cout <<c<<endl;
cout <<d<<endl;
}
函数模版注意事项
注意事项:
①自动类型推导,必须推导出一致的数据类型T,才可以使用
②模版必须要确定出T的数据类型,才可以使用
template<typename T> //typename可以用class代替
void mySwap(T &a,T &b){
T temp =a;
a = b;
b = temp;
}
void test01(){
int a = 10;
int b = 20;
char c ='c';
mySwap(a,b);//正确
mySwap(a,c);//错误,推导不一致的数据类型T
}
template<class T>
void func(){
cout <<"func调用"<<endl;
}
void test02(){
//模版必须要确定出T的数据类型,才可以使用
func<int>();
}
函数模版案例
案例描述:
①利用函数模版封装一个排序的函数,可以对不同数据类型数组进行排序
②排序规律从大到小,排序算法为选择排序
③分别利用char数组和int数组进行测试
template<typename T> //typename可以用class代替
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[max]<arr[j]){
max=j;
}
}
if(max!=i){
mySwap(arr[max],arr[i]);
}
}
}
template<class T>
void printArray(T arr[],int len){
for(int i =0;i<len;i++){
cout <<arr[i]<<" ";
}
cout<<endl;
}
void test(){
char charArr[]="ashhdh";
int num=sizeof(charArr)/sizeof(char);
mySort(charArr,num);
printArray(charArr,num);
}
普通函数与函数模版的区别
普通函数与函数模版区别
①普通函数调用时可以发送自动类型转换(隐式类型转换)
②函数模版调用时,如果利用自动类型推导,不会发生隐式类型转换
③如果利用显示指定类型的方式,可以发生隐式类型转换
int myAdd01(int a,int b){
return a+b;
}
//函数模版
template<class T>
T myAdd02(T a,T b){
return a+b;
}
void test01(){
int a =10;
int b =20;
char c='c';
cout <<myAdd01(a,c) <<endl;
cout <<myAdd02(a,b) <<endl;
cout <<myAdd02(a,c) <<endl;//函数模版调用时,如果利用自动类型推导,不会发生隐式类型转换
cout <<myAdd02<int>(a,c) <<endl;//如果利用显示指定类型的方式,可以发生隐式类型转换
}
普通函数和函数模版的调用规则
调用规则如下:
①如果函数模版和普通函数都可以实现,优先调用普通函数
②可以通过空模版参数列表来强制调用函数模版
③函数模版也可以发生重载
④如果函数模版可以产生更好的匹配,优先调用函数模版
总结:既然提供了的数模板,最好就不要提供普通函数,否则容易出现二义性
void myPrint(int a int b){
cout <<"调用的普通函数"<<endl;
}
template<class T>
void myPrint(T a,T b){
cout <<"调用的模版"<<endl;
}
template<class T>
void myPrint(T a,T b,T c){
cout <<"调用的重载模版"<<endl;
}
void test02(){
int a=10;
int b=20;
myPrint(a,b);//如果函数模版和普通函数都可以实现,优先调用普通函数
myPrint<>(a,b);//通过空模版参数列表来强制调用函数模版
myPrint(a,b,100);//函数模版也可以发生重载
char c1='a';
char c2='b';
myPrint(c1,c2);//如果函数模版可以产生更好的匹配,优先调用函数模版
}
模版的局限性
1、局限性:
模版的通用性并不是万能的
2、例如
template<class T>
void f(T a, T b){
a = b;
}
在上诉代码中提供的赋值操作,如果传入的a和b是一个数组,就无法实现了
template<class T>
void f(T a,T b){
if(a>b){...}
}
在上诉代码中,如果T的数据类型传入的是像Person这样的自定义数据类型,也无法正常运行
因此C++为了解决这些问题,提供模版的重载,可以为这些特定的类型提供具体化的模版
class Person{
pubilc:
Person(string name,int age){
this->m_Name=name;
this->m_Age=age;
}
string m_Name;
int m_Age;
};
template<class T>
bool myCompare(T &a,T &b){
if(a==b){
return true;
}
else{
return false;
}
}
//利用具体化Person的版本实现代码,具体化优先调用
template<>bool myCompare(Person &a,Person &b){
if(p1.m_Name==p2.m_Name&&p1.m_Age==p2.m_Age){
return true;
}
else{
return false;
}
}
voi test01(){
int a=10;
int b=20;
bool ret=myConpare(a,b);
if(ret){
cout <<"a==b"<<endl;
}
else{
cout <<"a!=b"<<endl;
}
}
void test02(){
Person p1("Tom",10);
Person p2("Tom",10);
bool ret=myConpare(p1,p2);
if(ret){
cout <<"p1==p2"<<endl;
}
else{
cout <<"p1!=p2"<<endl;
}
}更多推荐


所有评论(0)