您好,欢迎访问三七文档
当前位置:首页 > 临时分类 > 第10章 C++模板
C++语言程序设计第10章模板10.1函数模板10.2类模板10.1函数模板10.1.1问题的提出重载函数可以解决功能相同或相似的函数使用同一个函数名的问题。voidswap(char&x,char&y){chart=x;x=y;y=t;}voidswap(int&x,int&y){intt=x;x=y;y=t;}voidswap(float&x,float&y){floatt=x;x=y;y=t;}实际代码量并未减少。可使用函数模板减少大量代码。10.1函数模板10.1.2函数模板的定义templateclassT或类型名函数名(参数表){函数体}函数模板就像是一个带有类型参数的函数(参数T即为类型),编译程序会根据实际参数的类型确定参数的类型。templatetypenameT类型名函数名(参数表){函数体}例10.1定义用于变量交换的函数模板#includeiostream.htemplateclassTvoidswap(T&x,T&y){Ttemp=x;x=y;y=temp;}voidmain(void){chara='A',b='B';intc=123,d=456;doublex=12.3,y=45.6;swap(a,b);swap(c,d);swap(x,y);couta,bendl;coutc,dendl;coutx,yendl;}程序运行结果为:B,A456,12345.6,12.3T本身是一个类型参数,在调用函数swap()时,编译程序会根据实际参数的类型确定T的类型。例10.2插入排序函数模板,使用插入排序函数模板可以为不同数据类型的数组排序,如整型、字符型、实型等等,为了使程序具有通用性,设计函数模板InsertionSort()。插入排序的基本思想:每一步将一个待排序的元素按其关键字值的大小插入到已排序序列的合适位置,直到待排序元素全部插入完为止。例10.2(续一)templateclassTvoidInsertionSort(TA[],intn){inti,j;Ttemp;for(i=1;in;i++){//从A[i-1]开始向A[0]方向扫描各元素,寻找适当位置插入A[i]j=i;temp=A[i];while(j0&&tempA[j-1]){//当遇到temp=A[j-1]结束循环时,j便是应插入的位置//当遇到j==0结束循环时,则0是应插入的位置。A[j]=A[j-1];//将元素逐个后移,以便找到插入位置时可立即插入。j--;}A[j]=temp;}}例10.2(续二)#includeiostream.hvoidmain(){inta[10]={2,4,1,8,7,9,0,3,5,6};doubleb[10]={12.1,24.2,15.5,81.7,2.7,5.9,40.3,33.3,25.6,4.6};InsertionSort(a,10);InsertionSort(b,10);for(inti=0;i10;i++)couta[i];coutendl;for(i=0;i10;i++)coutb[i];coutendl;}程序运行结果为:01234567892.74.65.912.115.524.225.633.340.381.710.1.3函数模板产生的二义性例10.3使用函数模板产生的二意性#includeiostream.htemplateclassTTmax(Ta,Tb){returnab?a:b;}voidmain(void){inta=max(10.5,20);doubleb=max(10,20.6);coutaendl;coutbendl;}产生二意性,系统不能确定将其中的一个参数由整数转化为实数,还是应该将另一个参数由实数转化为整数。可使用强制类型转换解决:inta=max((int)10.5,20);doubleb=max((double)10,20.6);10.1.4模板函数的覆盖下列函数模板:templateclassTTmax(Ta,Tb){retumab?a:b;}对于简单的数据类型,如整型、实型、字符型数据,这个模板能够正常工作。对于字符串,用上述模板就会出现问题,因为对于字符串,不能使用运算符“”,要为其编写独立的max()函数。我们将函数模板生成的函数称为模板函数。如果某一函数的函数原型与函数模板生成的函数(模板函数)原型一致,称该函数为模板函数的覆盖函数。例10.4模板函数的覆盖#includestring.h#includeiostream.htemplateclassTTmax(Ta,Tb){returnab?a:b;}char*max(char*x,char*y){returnstrcmp(x,y)0?x:y;}voidmain(void){char*p=ABCD,*q=EFGH;p=max(p,q);inta=max(10,20);floatb=max(10.5,20.6);coutpendl;coutaendl;coutbendl;}程序运行结果为:EFGH2020.610.1.4模板函数的覆盖在进行函数调用时,编译程序采用如下策略确定调用哪个函数:(1)首先寻找一个实参与形参完全匹配的覆盖函数,如果找到,则调用该函数.(2)如果能通过函数模板生成实例函数,并且参数匹配,则调用该函数。(3)通过强制类型转换,寻找能够与实参匹白的覆盖函数,或通过函数模板生成的实例函数、如果找到则调用该函数。(4)如果所有努力失败,则给出出错信息。10.2类模板10.2.1问题的提出classA{inti;public:A(inta){…}voidset(intb){……}…};classB{doublei;public:B(doublea){…}voidset(doubleb){……}…};对应的类模板:templateclassTclassA{Ti;public:A(Ta){…}voidset(Tb){……}…};这两个类的方法都一样,只是一个数据类型是整型,另一个数据类型是实型。可以使用类模板简化代码类模板也称为参数化的类,用于为类型相似的类定义一种通用模式10.2类模板10.2.2类模板的定义template模板参数表class类模板名{成员声明}如果需要在类模板外定义类模板的成员函数,格式如下:template模板参数表类型类模板名参数::函数名(参数表){函数体}10.2类模板10.2.2类模板的定义(续)使用类模板建立对象的语法如下:类模板实参表对象1,对象2,…;系统会根据实参的类型,生成一个类(称为模板类),然后建立该类的对象。即对模板实例化生成类,再对类实例化生成对象。例10.5定义数组类的类模板,并利用成员函数对数组中的元素初始化。#includeiostream.htemplateclassTclassmyArray{public:myArray(intnSize,TInitial);~myArray(){delete[]m_pArray;}T&operator[](intnIndex)//重载运算符[]用于取得数组的元素{returnm_pArray[nIndex];}voidShow(intnNumElems,char*pszMsg=,boolbOneLine=true);voidSort(intnNumElems);protected:T*m_pArray;//保存数组起始地址intm_nSize;//数组的长度};例10.5(续一)templateclassTmyArrayT::myArray(intnSize,TInitVal){m_nSize=(nSize1)?nSize:1;m_pArray=newT[m_nSize];for(inti=0;im_nSize;i++)m_pArray[i]=InitVal;}templateclassTvoidmyArrayT::Show(intnNumElems,char*pszMsg,boolbOneLine){coutpszMsgendl;if(bOneLine){for(inti=0;inNumElems;i++)coutm_pArray[i]'';coutendl;}else{for(inti=0;inNumElems;i++)coutm_pArray[i]endl;}}构造函数为m_nSize赋值,并为数组申请存储空间,将数组的每个元素都赋值为InitVal。成员函数Show()显示数组元素的值,元素的个数由第一个参数指定,第二个参数为输出数组元素值之前,输出的提示信息,第三个参数确定数组元素是显示在一行上,还是多行。例10.5(续二)templateclassTvoidmyArrayT::Sort(intnNumElems){inti,j;Ttemp;for(i=1;inNumElems;i++){j=i;temp=m_pArray[i];while(j0&&tempm_pArray[j-1]){m_pArray[j]=m_pArray[j-1];j--;}m_pArray[j]=temp;}}成员函数Sort()使用插入排序法对数组元素排序(升序),其参数是数组中元素的个数。例10.5(续三)voidmain(){intnArr[10]={89,34,32,47,15,81,78,36,63,83};intcArr[10]={'C','W','r','Y','k','J','X','Z','y','s'};myArrayintIntegerArray(10,0);myArraycharCharArray(10,'');for(inti=0;i10;i++)IntegerArray[i]=nArr[i];for(i=0;i10;i++)CharArray[i]=cArr[i];IntegerArray.Show(10,Unsortedarrayis:);IntegerArray.Sort(10);IntegerArray.Show(10,Sortedarrayis:);coutendl;CharArray.Show(10,Unsortedarrayis:);CharArray.Sort(10);CharArray.Show(10,Sortedarrayis:);coutendl;}定义了两个类模板对象,分别为int型和char型,数组元素分别被初始化为0和空格程序运行结果为:Unsortedarrayis:89343247158178366383Sortedarrayis:15323436476378818389Unsortedarrayis:CWrYkJXZysSortedarrayis:CJWXYZkrsy例10.6使用缺省参数定义数组的类模板#includeiostream.htemplateclassT=intclassArray{T*data;intsize;public:Array(int);~Array();T&operator[](int);};templateclassTArrayT::Array(intn){data=newT[size=n];}templateclassTArrayT::~Array(){deletedata;}templateclassTT&ArrayT::operator[](inti){returndata[i];}注意:函数模板不能定义缺省参数,而类模板却可以定义缺省参数。例10.6(续)voidmain(void){inti;ArrayL1(10);//等价于ArrayintL1(10
本文标题:第10章 C++模板
链接地址:https://www.777doc.com/doc-3369510 .html