《【精品】c c++语言程序设计第13章 模板(可编辑.ppt》由会员分享,可在线阅读,更多相关《【精品】c c++语言程序设计第13章 模板(可编辑.ppt(37页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C C+语言程序设计 第13章 模板2023/3/10第第13章章 模板模板13.1 模板函数模板函数13.2 类模板模板13.3 综合合实例例2023/3/10l求两个数据中最小求两个数据中最小值的函数的函数min()的的实现过程。程。其中,其中,a和和b可以是整型、可以是整型、实型,当然也可以是用型,当然也可以是用户定定义的数据的数据类型。型。C+是是强类型型语言,参数言,参数a和和b的的类型在型在编译时就必就必须声明。因此需要声明。因此需要对不不同的数据同的数据类型分型分别定定义不同的版本。不同的版本。13.1 函数模板函数模板1.模板的作用模板的作用 int min(int a,int
2、 b)/求两个整数中的最小求两个整数中的最小值值 int temp;temp=ab?a:b;return temp;float min(float a,float b)/求两个求两个实实型数据中的最小型数据中的最小值值 float temp;temp=ab?a:b;return temp;13.1 函数模板函数模板l使用模板,把使用模板,把数据数据类型型本身作本身作为一个一个参数参数,这样就可以使用一套代就可以使用一套代码完成不同数据完成不同数据类型的数型的数据交据交换,实际上也使上也使编程程趋于于标准化。与声明和准化。与声明和定定义通常不在一起的普通函数不同,函数模版的通常不在一起的普通函数
3、不同,函数模版的定定义紧接其声明之后。其格式如下:接其声明之后。其格式如下:template 返回值类型返回值类型 函数名函数名(形参表)(形参表)/函数体函数体关键字不能省略参数项由关键字class后跟一个标识符组成13.1 函数模板函数模板编写函数模板的方法是:写函数模板的方法是:第一步第一步:定:定义一个普通的函数,数据一个普通的函数,数据类型采用具型采用具体的普通的数据体的普通的数据类型。型。第二步第二步:将数据:将数据类型参数化:将其中需要使用到型参数化:将其中需要使用到的具体数据的具体数据类型名型名(如如 int)全部替全部替换成由自己定成由自己定义的抽象的的抽象的类型参数名型参数
4、名(如如T)。第三步第三步:在函数:在函数头前用关前用关键字字template引出引出对类型参数名的声明。型参数名的声明。这样就把一个具体的函数改就把一个具体的函数改造成一个通用的函数模板:造成一个通用的函数模板:13.1 函数模板函数模板说明:明:(1)虽然函数模板中的然函数模板中的类型参数型参数T可以被可以被实例例化化为各种各种类型,其型,其实际类型取决于模板函数型取决于模板函数给出出的的实参参类型。但是,型。但是,实例化例化T的各模板函数的的各模板函数的实参之参之间必必须保持完全一致的保持完全一致的类型,否型,否则会出会出现语法法错误。13.1 函数模板函数模板【例例13.2】分析下面程
5、序的运行分析下面程序的运行结果。果。#include#include template template T min(T a,T b)T min(T a,T b)T temp;T temp;temp=ab?a:b;temp=ab?a:b;return temp;return temp;13.1 函数模板函数模板void main()void main()int i=8;int i=8;float d=10.2f;float d=10.2f;cout min(i,i)=min(i,i)cout min(i,i)=min(i,i)endl;endl;/正确,正确,正确,正确,调调用用用用min(i
6、nt,int)min(int,int)cout min(d,d)=min(d,d)cout min(d,d)=min(d,d)endl;endl;/正确,正确,正确,正确,调调用用用用min(float,float)min(float,float)cout min(i,d)=min(i,d)cout min(i,d)=min(i,d)endl;endl;/错误错误 13.1 函数模板函数模板l(2)区分两个)区分两个术语函数模板函数模板和和模板函数模板函数。其中其中函数模板是函数模板是对一一组函数的描述函数的描述,它不是一个,它不是一个实实在在的函数,在在的函数,编译系系统并不并不产生任何生任
7、何执行代行代码;而;而模板函数模板函数则是是类型参数型参数实例化之后的函数例化之后的函数。它它们俩之之间的关系就好像的关系就好像类与与对象的关系。象的关系。13.1 函数模板函数模板l(3)模板函数与重)模板函数与重载是密切相关的。从函数模是密切相关的。从函数模板板产生的生的模板函数都是同名的模板函数都是同名的,因此,因此编译器采用器采用重重载的解决方法的解决方法调用相用相应函数。注意,模板函数函数。注意,模板函数虽然然类似于重似于重载函数,但它要更函数,但它要更严格一些。函数格一些。函数被重被重载时,在每个函数体内可以,在每个函数体内可以执行不同的行不同的动作,作,但但同一函数模板同一函数模
8、板实例化后的所有模板函数都必例化后的所有模板函数都必须执行相同的行相同的动作。作。13.1 函数模板函数模板【例例13.3】分析以下程序的运行分析以下程序的运行结结果。果。#include#include#include#include template template T Sum(T*array,int size=0)T Sum(T*array,int size=0)/A /A T total=0;T total=0;return total;return total;13.1 函数模板函数模板template template T2 Sum(T1*array1,T2*array2,int
9、 size=0)T2 Sum(T1*array1,T2*array2,int size=0)/B/B T2 total=0;T2 total=0;for(int for(int i=0;isize;i+)total+=array1i+array2i;i=0;isize;i+)total+=array1i+array2i;return total;return total;13.1 函数模板函数模板char*Sum(char*s1,char*s2)char*Sum(char*s1,char*s2)/C /C char*str=new charstrlen(s1)+strlen(s2)+1;cha
10、r*str=new charstrlen(s1)+strlen(s2)+1;strcpy(str,s1);strcpy(str,s1);return strcat(str,s2);return strcat(str,s2);void main()void main()int iArr=0,1,2,3,4,5,6,7;int iArr=0,1,2,3,4,5,6,7;double dArr=0.2,1.2,2.2,3.2,4.2,5.2,6.2,7.2;double dArr=0.2,1.2,2.2,3.2,4.2,5.2,6.2,7.2;int iTotal=Sum(iArr,10);int
11、iTotal=Sum(iArr,10);/D /D char*p1=How;char*p1=How;13.1 函数模板函数模板char*p2=are you?;char*p2=are you?;p1=Sum(p1,p2);p1=Sum(p1,p2);/E /Edouble dTotal1=Sum(dArr,8);double dTotal1=Sum(dArr,8);/F /Fdouble dTotal2=Sum(iArr,dArr,8);double dTotal2=Sum(iArr,dArr,8);/G/GcoutThe sum of integer array is:coutThe sum
12、 of integer array is:iTotalendl;iTotalendl;coutThe sum of double array is:coutThe sum of double array is:dTotal1endl;dTotal1endl;coutThe sum of integer array and double coutThe sum of integer array and double array is:dTotal2endl;array is:dTotal2endl;coutThe sum of two strings is:coutThe sum of two
13、strings is:p1endl;p1endl;执行程序后,输出结果为:执行程序后,输出结果为:The sum of integer array is:0The sum of double array is:0The sum of integer array and double array is:57.6The sum of two strings is:How are you?13.1 函数模板函数模板在在C+编译时,函数模板和同名的非模板函数重,函数模板和同名的非模板函数重载时,编译器通器通过如下的匹配如下的匹配过程确定程确定调用哪一用哪一个函数:个函数:(1)先去匹配最符合函数名和参
14、数先去匹配最符合函数名和参数类型的函数型的函数调用,用,即即优先先调用用对应的一般函数(非模板函数)的一般函数(非模板函数)。如。如果参数完全匹配,果参数完全匹配,则调用重用重载函数。函数。(2)如果重如果重载函数的参数函数的参数类型不匹配,型不匹配,则去匹配函数去匹配函数模板模板,将其,将其实例化例化产生一个匹配的模板函数,如生一个匹配的模板函数,如果匹配成功,果匹配成功,则调用此模板函数。用此模板函数。13.1 函数模板函数模板(3)如果模板函数匹配不成功,如果模板函数匹配不成功,编译器器尝试通通过类型型转换,来,来检验调用是否和重用是否和重载函数匹配函数匹配,如果,如果是,是,则调用重用
15、重载函数。函数。(4)如果上述操作均不能如果上述操作均不能进行,行,则产生生编译错误。如果最后得到了多于一种如果最后得到了多于一种选择,那么,那么这个函数个函数调用有二用有二义性,指出是一种性,指出是一种错误的函数的函数调用。用。13.2 类模板模板 类模板可以模板可以让用用户为类声明一种模式,使得声明一种模式,使得类中的某些数据成中的某些数据成员、某些成、某些成员函数的参数、某函数的参数、某些成些成员函数的返回函数的返回值能取任意能取任意类型。型。定义类模板的格式为:定义类模板的格式为:template class 类名类名/类体类体;13.2 类模板模板如果需要在如果需要在类模板以外定模板
16、以外定义其成其成员函数,函数,则要采要采用以下的形式:用以下的形式:template返回值类型返回值类型 类名类名:函数名函数名(参数表参数表)/函数体函数体13.2 类模板模板 类模板不代表一个具体的、模板不代表一个具体的、实际的的类,而代,而代表若干个具有相同特性的表若干个具有相同特性的类,它是生成,它是生成类的的样板。板。实际上,上,类模板的使用就是将模板的使用就是将类模板模板实例化例化为一一个个具体的个个具体的类,即模板,即模板类,然后再通,然后再通过模板模板类建建立立对象。象。说明模板明模板类对象的格式象的格式为:对象对象1,对象对象n;13.2 类模板模板【例例13.4】堆堆栈类模
17、板模板Stack的使用。的使用。#include#include template template /定定定定义义堆堆堆堆栈类栈类的模板的模板的模板的模板class Stackclass Stack T*data;T*data;int topint top;/;/栈顶栈顶;int sizeint size;/;/堆堆堆堆栈栈的尺寸的尺寸的尺寸的尺寸int IsEmpty()int IsEmpty()return(top0)?1:0;return(top0)?1:0;/判断堆判断堆判断堆判断堆栈栈是否是否是否是否为为空空空空13.2 类模板模板int IsFull()int IsFull()r
18、eturn(top=size)?1:0;return(top=size)?1:0;/判断堆判断堆判断堆判断堆栈栈是否已是否已是否已是否已满满public:public:Stack(int n)Stack(int n)/初始化堆初始化堆初始化堆初始化堆栈栈 data=new Tn;data=new Tn;size=n;size=n;top=0;top=0;Stack()Stack()delete data;delete data;void push(T a);void push(T a);/压压入操作入操作入操作入操作T pop();T pop();/弹弹出操作出操作出操作出操作;13.2 类模
19、板模板template template /类类模板的成模板的成模板的成模板的成员员函数的函数的函数的函数的实现实现void Stack:push(T a)void Stack:push(T a)/堆堆堆堆栈类栈类StackStack的的的的压压入操作的入操作的入操作的入操作的实现实现 if(IsFull()if(IsFull()coutFull of Stackendl;coutFull of Stackendl;else else *(data+top+)=a;*(data+top+)=a;13.2 类模板模板template class Ttemplate /类类模板的成模板的成模板的成
20、模板的成员员函数的函数的函数的函数的实现实现T Stack:pop()T Stack:pop()/堆堆堆堆栈类栈类StackStack的的的的弹弹出操作的出操作的出操作的出操作的实现实现 if(IsEmpty()if(IsEmpty()coutEmpty of coutEmpty of Stackendl;Stackendl;return(*(data+-top);return(*(data+-top);13.2 类模板模板void main()void main()/测试测试堆堆堆堆栈类栈类模板模板模板模板StackStack cout-cout-整数堆整数堆整数堆整数堆栈栈-n;-n;St
21、ack x(5);Stack x(5);/定定定定义义一个可以放一个可以放一个可以放一个可以放5 5个整型元素的堆个整型元素的堆个整型元素的堆个整型元素的堆栈栈x.push(1);x.push(1);x.push(2);x.push(2);coutx.pop()endl;coutx.pop()endl;x.push(3);x.push(3);x.push(4);x.push(4);coutx.pop()endl;coutx.pop()endl;coutx.pop()endl;coutx.pop()endl;13.2 类模板模板coutx.pop()endl endl;coutx.pop()en
22、dl endl;cout-cout-浮点数堆浮点数堆浮点数堆浮点数堆栈栈-n;-n;Stack y(6);Stack y(6);/定定定定义义一个可以放一个可以放一个可以放一个可以放6 6个浮点型元素的堆个浮点型元素的堆个浮点型元素的堆个浮点型元素的堆栈栈y.push(2.1f);y.push(2.1f);y.push(3.4f);y.push(3.4f);couty.pop()endl;couty.pop()endl;y.push(5.2f);y.push(5.2f);y.push(2.5f);y.push(2.5f);couty.pop()endl;couty.pop()endl;cout
23、y.pop()endl;couty.pop()endl;couty.pop()endl endl;couty.pop()endl endl;程序运行结果如下:程序运行结果如下:-整数堆栈整数堆栈-2431-浮点数堆栈浮点数堆栈-3.42.55.22.113.3 综合合实例例【例例13.5】使用使用类模板,模板,编写一个写一个对数数组进行排行排序、序、查找和求元素和的程序。找和求元素和的程序。分析:分析:分析:分析:设计一个类模板设计一个类模板templateclass Array,用于对,用于对T类型的数组进行排序、查找和类型的数组进行排序、查找和求元素和,然后由此产生模板类求元素和,然后由此
24、产生模板类Array和和Array。13.3 综合合实例例#include#include#include#include template template class Array class Array T*set;T*set;int n;int n;public:public:Array(T*data,int i)set=data;n=i;Array(T*data,int i)set=data;n=i;Array()Array()13.3 综合合实例例 void sort();void sort();/排序排序排序排序 int seek(T key);int seek(T key);/查
25、查找指定的元素找指定的元素找指定的元素找指定的元素 T sum();T sum();/求和求和求和求和 void disp();void disp();/显显示所有的元素示所有的元素示所有的元素示所有的元素 ;13.3 综合合实例例template template void Array:sort()void Array:sort()int i,j;int i,j;T temp;T temp;for(i=1;in;i+)for(i=1;i=i;j-)for(j=n-1;j=i;j-)if(setj-1setj)if(setj-1setj)temp=setj-1;setj-1=setj;temp
26、=setj-1;setj-1=setj;setj=temp;setj=temp;13.3 综合合实例例template template int Array:seek(T key)int Array:seek(T key)int i;int i;for(i=0;in;i+)for(i=0;in;i+)if(seti=key)if(seti=key)return i+1;return i+1;return-1;return-1;13.3 综合合实例例template template T Array:sum()T Array:sum()T s=0;int i;T s=0;int i;for(i=
27、0;in;i+)for(i=0;in;i+)s+=seti;s+=seti;return s;return s;13.3 综合合实例例template template void Array:disp()void Array:disp()int i;int i;for(i=0;in;i+)for(i=0;in;i+)coutseti ;coutseti ;coutendl;coutendl;13.3 综合合实例例void main()void main()int a=6,3,8,1,9,4,7,5,2;int a=6,3,8,1,9,4,7,5,2;double b=2.3,6.1,1.5,8
28、.4,6.7,3.8;double b=2.3,6.1,1.5,8.4,6.7,3.8;Arrayarr1(a,9);Arrayarr1(a,9);Arrayarr2(b,6);Arrayarr2(b,6);cout cout 序列序列序列序列1:endl;1:endl;cout cout 原序列原序列原序列原序列:;arr1.disp();:;arr1.disp();cout 8cout 8在序列在序列在序列在序列1 1中的位置中的位置中的位置中的位置:arr1.seek(8)endl;:arr1.seek(8)endl;13.3 综合合实例例 arr1.sort();arr1.sort()
29、;cout cout 排序后排序后排序后排序后:;arr1.disp();:;arr1.disp();cout cout 序列序列序列序列2:endl;2:endl;cout cout 原序列原序列原序列原序列:;arr2.disp();:;arr2.disp();cout 8.4cout 8.4在序列在序列在序列在序列2 2中的位置中的位置中的位置中的位置:arr2.seek(8.4)endl;:arr2.seek(8.4)endl;arr2.sort();arr2.sort();cout cout 排序后排序后排序后排序后:;arr2.disp();:;arr2.disp();程序的执行结果为:程序的执行结果为:序列序列1:原序列:原序列:6 3 8 1 9 4 7 5 2 8在序列在序列1中的位置:中的位置:3 排序后:排序后:1 2 3 4 5 6 7 8 9 序列序列2:原序列:原序列:2.3 6.1 1.5 8.4 6.7 3.8 8.4在序列在序列2中的位置:中的位置:4 排序后:排序后:1.5 2.3 3.8 6.1 6.7 8.4 小小结l模板的概念;模板的概念;l函数模板和模板函数的定函数模板和模板函数的定义与与应用;用;l类模板与模板模板与模板类的定的定义与与应用用
限制150内