您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > 第八章-函数模板与类模板
第8章模板8.1模板的概念问题的引入:一些函数的功能相同,唯一的区别只在于处理对象的数据类型不同,若用函数重载实现,则需编写多个函数:例:intmax(inti,intj){returnij?i:j;}floatmax(floati,floatj){returnij?i:j;}charmax(chari,charj){returnij?i:j;}这些函数执行的功能是相同的,只是参数类型和函数返回类型不同,能否为上述这些函数只写出一套代码呢?Tmax(Tx,Ty){return(xy)?x:y;}模板运算对象的类型不是实际的数据类型,而是一种参数化的类型,即是把数据类型作为模板的参数。模板是实现代码重用机制的一种工具。模版(函数模版和类模版)模版函数实例化模版类对象实例化实例化8.2函数模板与模板函数函数模版:建立一个通用函数,其函数返回类型和形参类型不具体指定,用一个虚拟的类型来代表,这个通用函数就称为函数模版。8.1函数模板的声明函数模板的一般说明形式如下:templatetypename类型参数返回类型函数名(模板形参表){函数体}每个类型参数之前都有一个关键字class或typename。多个类型参数之间用逗号分隔。作用:说明其后的参数是一个虚拟的类型名例如,将求最大值函数max()定义成函数模板,如下所示:templateclassTTmax(Tx,Ty){return(xy)?x:y;}也可以定义成如下形式:templatetypenameTTmax(Tx,Ty){return(xy)?x:y;}其中,T为类型参数,它既可取系统预定义的数据类型,又可以取用户自定义的类型。函数模板参数表的类型参数可以用于函数返回值,也可用于函数参数表及函数体中。–说明:–(1)函数模板本身不是函数,是生成函数的“模板”。经实例化后才得到真正的函数。–(2)实例化是指用某一具体的实际数据类型替代模板中的类型参数的过程。8.2.2函数模板的使用函数模板的使用就是将函数模板的实例化为具体的函数。函数模板的实例化由编译器来完成。编译系统根据函数调用的实际参数类型自动完成函数模板的实例化。当编译系统发现有一个函数调用:函数名(模板实参表);时,将根据模板实参表中的类型生成一个函数即模板函数。该模板函数的函数体与函数模板的函数定义体相同。【例8.1】函数模板的使用。#includeiostream.htemplateclassTTmax(Tx,Ty){return(xy)?x:y;}main(){inti1=10,i2=56;floatf1=12.5,f2=24.5;doubled1=50.344,d2=4656.346;charc1='k',c2='n';coutThemaxofi1,i2is:max(i1,i2)endl;coutThemaxoff1,f2is:max(f1,f2)endl;coutThemaxofd1,d2is:max(d1,d2)endl;coutThemaxofc1,c2is:max(c1,c2)endl;return0;}总结:函数模板提供了一类函数的抽象,代表了一类函数。模板函数表示一具体的函数。函数模版max(T,T)模版函数max(int,int)模版函数max(double,double)模版函数max(char,char)实例化实例化实例化#includeiostream.htemplateclassATATsum(AT*array,intsize=0){ATtotal=0;for(inti=0;isize;i++)total+=array[i];returntotal;}例:有关指针的函数模板举例。intint_array[]={1,2,3,4,5,6};doubled_array[]={1.1,2.2,3.3,4.4,5.5};main(){intitotal=sum(int_array,6);doubledtotal=sum(d_array,5);coutitotal=itotalendl;coutdtotal=dtotalendl;}1)在template语句与函数模板定义之间不许有别的语句。templateclassTinti;//错误Tmin(Tx,Ty){return(xy)?x:y;}函数模板定义时应注意的问题:2)调用模板函数时,应保证函数的实参类型与类型参数完全匹配。函数模板在实例化过程中不做任何类型转换。例如:已知函数模板max的两个形参都是类型参数TYPE类型的,则以下两个应用错误:max(10,10.5);//一个实参是整型,另一个是double型,类型不同max(10,obj1);//一个实参是整型,另一个是MY_CLASS类型,都无法实例化3)在函数模板中允许使用多个类型参数。在template定义部分的每个类型参数前必须有关键字class(或typename)。#includeiostream.htemplatetypenametype1,typenametype2voidmyfunc(type1x,type2y){coutx’’yendl;}intmain(){myfunc(10,hao);myfunc(0.123,10);return0;}例:有两个类型参数的函数模板。4)函数模板也可以重载。例:函数模板重载。templatetypenameTypeTypemin(Typex,Typey){return(xy)?x:y;}templatetypenameTypeTypemin(Typex,Typey,Typez){Typet;t=(xy)?x:y;return(tz)?t:z;}5)函数模板与同名的非模板函数也可以重载。调用顺序:1)参数完全匹配的非模板函数;2)函数模板,将其实例化,产生模板函数;如果以上2种情况都未找到匹配函数,则按出错处理。#includeiostream.htemplatetypenameATATmin(ATx,ATy){cout调用模板函数;return(xy)?x:y;}intmin(intx,inty){cout调用非模板函数;return(xy)?x:y;}intmain(){inti1=10,i2=56;doubledl=50.34,d2=23,56;charc1='k',c2='c';cout较小的整数是:min(i1,i2)endl;cout较小的双精度型数是:min(d1,d2)endl;cout较小的字符串是:min(c1,c2)endl;return0;}6)在函数模板定义template中给出的每一个形式类属参数都必须在函数形参表中至少出现一次:–如:templateclassT1,classT2voidfun(T1x,T2y){……}–错误的用法㊀templateclassTYPETYPE*func(){……}㋥templateclassTYPEvoidfunc(){TYPEobj;……}8.3类模板与模板类类模板:建立一个通用类,其数据成员,成员函数的返回类型和形参类型不具体指定,用一个虚拟的类型来代表。使用类模版定义对象时,系统会根据实参的类型来取代类模版中虚拟类型,从而实现不同类的功能。定义一个类模板,其格式如下:templatetypename类型参数class类名{//…类模板定义体};例:定义类模板CThree储存三个成员变量,返回这三个成员变量的和。templateclassTclassCThree{public:CThree(Tt1,Tt2,Tt3):a(t1),b(t2),c(t3){}Tsum(){returna+b+c;}private:Ta,b,c;};说明:(1)定义模板时应至少确定一个模板参数;(2)类模板的定义格式与类的定义格式相同,包含说明部分和实现部分;在类体外定义时,其格式如下:template模板参数表T返回值类型类名T::函数名(参数表){函数体}templateclassTclassCThree{public:CThree(Tt1,Tt2,Tt3);Tsum();private:Ta,b,c;};templateclassTCThreeT::CThree(Tt1,Tt2,Tt3){a=t1;b=t2;c=t3;}templateclassTTCThreeT::sum(){returna+b+c;}类模板不是代表一个具体的、实际的类,而是代表着一类类。实际上,类模板的使用就是将类模板实例化成一个具体的类,即为模板类。它的格式为:类模板名实际的类型对象名;类模板名实际的类型对象名(参数);intmain(){CThreeinta(3,5,1);CThreefloatb(3.3,5.1,1.2);cout“三个整数的和是”a.sum()endl;cout“三个实数的和”b.sum()endl;return0;}类模板CThreeT模板类CThreeint实例化对象b实例化对象a实例化模板类CThreefloat实例化例:栈类模板的使用。#includeiostream.hconstintsize=10;templateclassType//声明一个类模板classstack{public:voidinit(){tos=0;}voidpush(Typech);//参数取Type类型Typepop();//返回类型取Type类型private:Typestck[size];//数组的类型为类型参数Type,inttos;};templateclassType//每个成员函数都要加上模板声明voidstackType::push(Typeob)//类名为stackType{if(tos==size){coutstackisfull;return;}stck[tos]=ob;tos++;}templateclassTypeTypestackType::pop(){if(tos==0){coutstackisempty;return0;}tos--;returnstck[tos];}intmain(){//定义字符堆栈stackchars1,s2;//创建两个模板参数为char型的对象inti;s1.init();s2.init();s1.push('a');s2.push('x');s1.push('b');s2.push('y');s1.push('c');s2.push('z');for(i=0;i3;i++)coutpops1:s1.pop()endl;for(i=0;i3;i++)coutpops2:s2.pop()endl;//定义整型堆栈stackintis1,is2;//创建两个模板参数为int型的对象is1.init();is2.init();is1.push(1);is2.push(2);is1.push(3);is2.push(4);is1.push(5);is2.push(6);for(i=0;i3;i++)coutpopis1:is1.pop()endl;for(i=0;i3;i++)coutpopis2:is2.pop()endl;return0;}例:使用两个类型参数的类模板。#includeiostream.htemplateclassT1,classT2classmyclass{public:myclass(T1a,T2b){i=a;j=b;}voidshow(){couti=ij=jendl;}private:
本文标题:第八章-函数模板与类模板
链接地址:https://www.777doc.com/doc-7817024 .html