Object-OrientedProgramming计算机科学与技术系C++面向对象技术程序设计主讲教师:吴芸Object-OrientedProgramming计算机科学与技术系教材:名称:C++面向对象程序设计教程(第3版)作者:陈维兴,林小茶出版:清华大学出版社Object-OrientedProgramming计算机科学与技术系第6章:模板与异常处理6.1模板的概念6.2函数模板与模板函数6.3类模板与模板类6.4异常处理6.5应用举例Object-OrientedProgramming计算机科学与技术系6.1模板的概念模板是实现代码重用机制的一种工具,它可以实现类型参数化,即把类型定义为参数,从而实现了真正的代码重用。模板分为函数模板和类模板,它们分别允许用户构造模板函数和模板类。Object-OrientedProgramming计算机科学与技术系6.1模板的概念模板(函数模板和类模板)模板函数模板类对象实例化实例化实例化Object-OrientedProgramming计算机科学与技术系第6章:模板与异常处理6.1模板的概念6.2函数模板与模板函数6.3类模板与模板类6.4异常处理6.5应用举例Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数函数模板的一般说明形式如下:templatetypename[或class]类型参数返回类型函数名(模板形参表){函数体}其中,template是一个声明模板的关键字,它表示声明一个模板。Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数例如:将求最大值函数max()定义成函数模板,如下所示:templatetypenameTTmax(Tx,Ty){return(xy)?x:y;}也可以定义成如下形式:templateclassTTmax(Tx,Ty){return(xy)?x:y;}其中,T为类型参数,它既可取系统预定义的数据类型,又可以取用户自定义的类型。Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数将T实例化的参数称为模板实参,用模板实参实例化的函数称为模板函数。当编译系统发现有一个函数调用:函数名(模板实参表);将根据模板实参表中的类型生成一个函数即模板函数。该模板函数的函数体与函数模板的函数定义体相同。Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数例6.1函数模板的使用。//p261#includeiostream.htemplatetypenameTTmax(Tx,Ty){return(xy)?x:y;}intmain(){inti1=10,i2=50;doubled1=50.344,d2=4656.346;charc1='k',c2='n';coutThemaxofi1,i2is:max(i1,i2)endl;coutThemaxofd1,d2is:max(d1,d2)endl;coutThemaxofc1,c2is:max(c1,c2)endl;return0;}Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数例6.2有关指针的函数模板//p263#includeiostream.htemplatetypenameTTsum(T*array,intsize=0){Ttotal=0;for(inti=0;isize;i++)total+=array(i);returntotal;}intint_array=[1,2,3,4,5,6,7,8,9,10];doubledouble_array=[1.1,2.2,3.3,4.4,5.5,6.6,7.7,8.8,9.9,10.10];intmain(){intitotal=sum(int_array,10);doubledtotal=sum(double_array,10);cout“itotal=“itotalendl;cout“dtotal=“dtotalendl;return0;}Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数说明1.在template语句与函数模板定义语句之间不能有别的语句。templateclassTinti;//错误Tmax(Tx,Ty){return(xy)?x:y;}2.模板函数类似于重载函数,只不过它更严格一些。在函数重载时,每个函数体可以执行不同的动作。但同一函数模板实例化后的所有模板函数都必须执行相同的动作。3.在函数模板中允许使用多个类型参数,每个类型参数前必须有关键字class/typename。Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数例6.3有两个类型参数的函数模板。//p265#includeiostream.htemplatetypenametype1,typenametype2voidmyfunc(type1x,type2y){coutx““yendl;}intmain(){myfunc(10,hao);myfunc(0.123,10L);return0;}Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数4.同一般函数一样,函数模板也可以重载.例6.4:#includeiostream.h//p264templatetypenametypetypemax(typex,typey){return(xy)?x:y;}templatetypenametypetypemax(typex,typey,typez){typet;t=(xy)?x:y;return(tz)?t:z;}intmain(){intm=10,n=20,max2;doublea=10.1,b=20.2,c=30.3,max3;max2=max(m,n);max3=max(a,b,c);coutmax(m,n)=max2endl;coutmax(a,b,c)=max3endl;return0;}Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数5.函数模板与同名的非模板函数可以重载.例6.5:#includeiostream.h//p265templatetypenameATATmax(ATx,ATy){cout“调用模板函数:”;return(xy)?x:y;}intmax(intx,inty){cout“调用非模板函数:”;return(xy)?x:y;}intmain(){inti1=10,i2=20;doubled1=10.1,d2=20.2;charc1=‘k’,c2=‘n’;cout“较小的整数是:max(i1,i2)endl;cout“较小的双精度数是:max(d1,d2)endl;cout“较小的字符串是:max(c1,c2)endl;return0;}Object-OrientedProgramming计算机科学与技术系6.2函数模板与模板函数在C++中,函数模板和同名的非模板函数重载时,调用的顺序遵循以下约定:1)寻找一个参数完全匹配的函数,如果有则调用之。2)寻找一个函数模板,将其实例化,产生一个匹配的模板函数,若匹配则调用之。3)若1步和2步都失败,就再试低一级的对函数调用方法,例如通过类型转换可产生参数匹配等。若找到了则调用之。4)若1步2步3步都未找到匹配的参数,则返回一个错误的调用。5)若在1步有多于一个的选择,即函数调用存在二义性,则也是错误的调用。Object-OrientedProgramming计算机科学与技术系第6章:模板与异常处理6.1模板的概念6.2函数模板与模板函数6.3类模板与模板类6.4异常处理6.5应用举例Object-OrientedProgramming计算机科学与技术系6.3类模板与模板类类模板允许用户为类定义一种模式,使得类中的某些数据成员,某些成员函数的参数或返回值,能取任意数据类型。Object-OrientedProgramming计算机科学与技术系6.3类模板与模板类定义一个类模板与定义函数模板的格式类似,必须以关键字template开始,然后是类名,其格式如下:templatetypename[或class]Typeclass类名{//…};模板参数类型参数Object-OrientedProgramming计算机科学与技术系6.3类模板与模板类在类定义中,欲采用通用数据类型的数据成员,成员函数的参数或返回值前面需要加上Type。constintsize=10templateclassTypeclassstack{public:voidinit(){tos=0;}voidpush(Typech);Typepop();private:Typestck[size];inttos;};Object-OrientedProgramming计算机科学与技术系6.3类模板与模板类在类体外定义有模板形参的成员函数时,需要在函数体外进行模板声明,并且在函数名前的类名后缀上“Type”templateclassTypevoidstackType::push(Typeob){if(tos==size){cout“stackisfull”;return;}stck[tos]=ob;tos++;}Object-OrientedProgramming计算机科学与技术系6.3类模板与模板类在类体外定义有模板形参的成员函数时,需要在函数体外进行模板声明,并且在函数名前的类名后缀上“Type”templateclassTypeTypestackType::pop(){if(tos==0){cout“stackisempty”;return0;}tos--;returnstck[tos];}Object-OrientedProgramming计算机科学与技术系6.3类模板与模板类类模板不是代表一个具体的、实际的类,而是代表着一类类。实际上,类模板的使用就是将类模板实例化成一个具体的类,它的格式为:类模板名实际的类型对象名;例:stackchars1,s2;Object-OrientedProgramming计算机科学与技术系6.3类模板与模板类例6.8使用栈类模板//p269#includeiostream.hconstintsize=10;templateclassType//声明一个类模板classstack{public:voidinit(){tos=0;}voidpush(Typech);//参数取Type类型Typepop();//返回类型取Type类型private:Typestck[size];//数组的类型为类型参数Type,即可取任意类型inttos;};templateclassTypevoidstackType::push(Typeob){//......}Object-OrientedProgramming计算机科学与技术系6.3类模板与模板类templateclassTypeTypestackType::pop(){//......}intmain(){//定义字符堆栈stackchars;//创建两个模板参数为char型的对象inti;s.init();s.push('a');s.push('b');s.push('c');for(i=0;i3;i++)coutpops: