《C程序设计教程与实验指导杨国兴模板.ppt》由会员分享,可在线阅读,更多相关《C程序设计教程与实验指导杨国兴模板.ppt(26页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、C程序设计教程与实验指导杨国兴模板 Still waters run deep.流静水深流静水深,人静心深人静心深 Where there is life,there is hope。有生命必有希望。有生命必有希望第7章模板7.1函数模板7.2模板函数的覆盖7.3类模板7.1 函数模板1.问题的提出重载函数重载函数可以解决功能相同或相似的函数可以解决功能相同或相似的函数使用同一个函数名使用同一个函数名的的问题。问题。void swap(char&x,char&y)void swap(char&x,char&y)char t=x;char t=x;x=y;x=y;y=t;y=t;void swa
2、p(int&x,int&y)void swap(int&x,int&y)int t=x;int t=x;x=y;x=y;y=t;y=t;第7章 模板void swap(float&x,float&y)float t=x;x=y;y=t;实际代码量并未实际代码量并未减少。可使用函数模减少。可使用函数模板减少大量代码。板减少大量代码。7.1 函数模板2.函数模板的定义templatetemplate或或类型名类型名 函数名(参数表)函数名(参数表)函数体函数体函数模板函数模板就像是一个带有就像是一个带有类型参数类型参数的函数的函数(参数参数T T即为类型即为类型),编译程序会根据实际参数的类型确定
3、参数的类型。编译程序会根据实际参数的类型确定参数的类型。第7章 模板templatetemplate类型名类型名 函数名(参数表)函数名(参数表)函数体函数体 例例7.17.1定义用于变量交换的函数模板定义用于变量交换的函数模板#include using namespace std;template void swap(T&x,T&y)T temp=x;x=y;y=temp;void main(void)char a=A,b=B;int c=123,d=456;double x=12.3,y=45.6;swap(a,b);swap(c,d);swap(x,y);cout a ,b endl;
4、cout c ,d endl;cout x ,y endl;第7章 模板程序运行结果为:程序运行结果为:B,AB,A456,123456,12345.6,12.345.6,12.3T本身是一个类型参数,在调用函本身是一个类型参数,在调用函数数swap()时,编译程序会根据实()时,编译程序会根据实际参数的类型确定际参数的类型确定T的类型。的类型。例例7.27.2插入排序函数模板,使用插入排序函数模板可以为不插入排序函数模板,使用插入排序函数模板可以为不同数据类型的数组排序,如整型、字符型、实型等等,为了使同数据类型的数组排序,如整型、字符型、实型等等,为了使程序具有通用性,设计函数模板程序具有
5、通用性,设计函数模板InsertionSortInsertionSort()。()。插入排序的基本思想:每一步将一个待排序的元素按其关键字值的大小插入到已排序序列的合适位置,直到待排序元素全部插入完为止。第7章 模板例例7.27.2(续一)(续一)template void InsertionSort(T A,int n)int i,j;T temp;for(i=1;i 0&temp=Aj-1结束循环时,结束循环时,j便是应插入的位置便是应插入的位置 /当遇到当遇到j=0结束循环时,则结束循环时,则0是应插入的位置。是应插入的位置。Aj=Aj-1;/将元素逐个后移,以便找到插入位置时可立即插入
6、。将元素逐个后移,以便找到插入位置时可立即插入。j-;Aj=temp;第7章 模板例例7.27.2(续二)(续二)#include using namespace std;void main()int a10=2,4,1,8,7,9,0,3,5,6;double b10=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);cout a0 a1 a2 a3 ;cout a4 a5 a6 a7 ;cout a8 a9 endl;cout b0 b1 b2 b3 ;cout b4
7、 b5 b6 b7 ;cout b8 b9 endl;第7章 模板程序运行结果为:程序运行结果为:012345678901234567892.74.65.912.115.524.225.633.340.381.72.74.65.912.115.524.225.633.340.381.7例例7.37.3使用函数模板产生的二意性使用函数模板产生的二意性#include using namespace std;template T max(T a,T b)return ab?a:b;void main(void)int a=max(10.5,20);double b=max(10,20.6);cou
8、t a endl;cout b endl;第7章 模板产生二意性,系统不能确定将其中的一产生二意性,系统不能确定将其中的一个参数由整数转化为实数,还是应该将个参数由整数转化为实数,还是应该将另一个参数由实数转化为整数另一个参数由实数转化为整数。可使用强制类型转换解决:可使用强制类型转换解决:int a=max(int)10.5,20);double b=max(double )10,20.6);返 回7.2 模板函数的覆盖下列函数模板:下列函数模板:templatetemplateTmax(Ta,Tb)Tmax(Ta,Tb)retumab?a:b;retumab?a:b;对于简单的数据类型,如
9、对于简单的数据类型,如整型、实型、字符型整型、实型、字符型数据,这个模板数据,这个模板能够正常工作。对于能够正常工作。对于字符串字符串,用上述模板就会,用上述模板就会出现问题出现问题,因为对,因为对于字符串,不能使用运算符于字符串,不能使用运算符“”,要为其编写独立的,要为其编写独立的maxmax()函()函数。数。我们将函数模板生成的函数称为我们将函数模板生成的函数称为模板函数模板函数。如果某一函数的函。如果某一函数的函数原型与函数模板生成的函数(模板函数)原型一致,称该函数数原型与函数模板生成的函数(模板函数)原型一致,称该函数为模板函数的为模板函数的覆盖函数覆盖函数。第7章 模板例例7.
10、47.4模板函数的覆盖模板函数的覆盖#include#include using namespace std;template T max(T a,T b)return ab?a:b;char*max(char*x,char*y)return strcmp(x,y)0?x:y;void main(void)char*p=ABCD,*q=EFGH;p=max(p,q);int a=max(10,20);float b=max(10.5,20.6);cout p endl;cout a endl;cout b endl;第7章 模板程序运行结果为:程序运行结果为:EFGHEFGH202020.62
11、0.67.2 模板函数的覆盖在进行函数调用时,编译程序采用如下策略确定调用哪个函数:在进行函数调用时,编译程序采用如下策略确定调用哪个函数:(1 1)首先寻找一个实参与形参完全匹配的)首先寻找一个实参与形参完全匹配的覆盖函数覆盖函数,如果找到,如果找到,则调用该函数则调用该函数(2 2)如果能通过)如果能通过函数模板生成实例函数函数模板生成实例函数,并且参数匹配,则调用,并且参数匹配,则调用该函数。该函数。(3 3)通过)通过强制类型转换强制类型转换,寻找能够与实参匹白的覆盖函数,或通,寻找能够与实参匹白的覆盖函数,或通过函数模板生成的实例函数、如果找到则调用该函数。过函数模板生成的实例函数、
12、如果找到则调用该函数。(4 4)如果所有努力失败,则给出出错信息。)如果所有努力失败,则给出出错信息。第7章 模板 返 回7.3 类模板1.问题的提出 class A class A int i;int i;public:public:A(int a)A(int a)void set(int b)void set(int b);class B class B double i;double i;public:public:B(double a)B(double a)void set(double b)void set(double b);第7章 模板对应的类模板:对应的类模板:template
13、 class A T i;public:A(T a)void set(T b);这两个类的方法都一这两个类的方法都一样,只是一个数据类样,只是一个数据类型是整型,另一个数型是整型,另一个数据类型是实型。可以据类型是实型。可以使用类模板简化代码使用类模板简化代码类模板也称为参数化类模板也称为参数化的类,用于为类型相的类,用于为类型相似的类定义一种通用似的类定义一种通用模式模式7.3 类模板2.类模板的定义 templatetemplate classclass类模板名类模板名成员声明成员声明如果需要在类模板外定义类模板的成员函数,格式如下:如果需要在类模板外定义类模板的成员函数,格式如下:tem
14、platetemplate 类型类型 类模板名类模板名:函数名(参数表)函数名(参数表)函数体函数体第7章 模板7.3 类模板2.类模板的定义(续)使用类模板建立对象的语法如下:使用类模板建立对象的语法如下:类模板类模板 对象对象1 1,对象,对象2 2,;系统会根据实参的类型,生成一个类(称为系统会根据实参的类型,生成一个类(称为模板类模板类),然后建),然后建立该类的对象。即对模板实例化生成类,再对类实例化生成对象。立该类的对象。即对模板实例化生成类,再对类实例化生成对象。第7章 模板例例7.57.5定义数组类的类模板,并利用成员函数对数组中的元定义数组类的类模板,并利用成员函数对数组中的
15、元素初始化。素初始化。#include using namespace std;template class myArraypublic:myArray(int nSize,T InitVal);myArray()delete m_pArray;T&operator(int nIndex)/重载运算符用于取得数组的元素return m_pArraynIndex;void Show(int nNumElems,char*pszMsg=,bool bOneLine=true);void Sort(int nNumElems);protected:T*m_pArray;/保存数组起始地址int m_
16、nSize;/数组的长度;第7章 模板例例7.57.5(续一)(续一)templatemyArray:myArray(int nSize,T InitVal)m_nSize=(nSize1)?nSize:1;m_pArray=new Tm_nSize;for(int i=0;im_nSize;i+)m_pArrayi=InitVal;templatevoid myArray:Show(int nNumElems,char*pszMsg,bool bOneLine)cout pszMsgendl;if(bOneLine)for(int i=0;inNumElems;i+)cout m_pArra
17、yi ;cout endl;elsefor(int i=0;inNumElems;i+)cout m_pArrayiendl;第7章 模板构造函数为构造函数为m_nSize赋值,并为数组申赋值,并为数组申请存储空间,将数组的每个元素都赋值请存储空间,将数组的每个元素都赋值为为InitVal。成员函数成员函数Show()显示数组元()显示数组元素的值,元素的个数由第一个参素的值,元素的个数由第一个参数指定,第二个参数为输出数组数指定,第二个参数为输出数组元素值之前,输出的提示信息,元素值之前,输出的提示信息,第三个参数确定数组元素是显示第三个参数确定数组元素是显示在一行上,还是多行。在一行上,还
18、是多行。例例7.57.5(续二)(续二)templatevoid myArray:Sort(int nNumElems)int i,j;T temp;for(i=1;i 0&temp m_pArrayj-1)m_pArrayj=m_pArrayj-1;j-;m_pArrayj=temp;第7章 模板成员函数成员函数Sort()使用插入排序法对数()使用插入排序法对数组元素排序(升序),其参数是数组中组元素排序(升序),其参数是数组中元素的个数。元素的个数。例例7.57.5(续三)(续三)void main()int nArr10=89,34,32,47,15,81,78,36,63,83;in
19、t cArr10=C,W,r,Y,k,J,X,Z,y,s;myArray IntegerArray(10,0);myArray CharArray(10,);for(int i=0;i10;i+)IntegerArrayi=nArri;for(i=0;i10;i+)CharArrayi=cArri;IntegerArray.Show(10,Unsorted array is:);IntegerArray.Sort(10);IntegerArray.Show(10,Sorted array is:);cout endl;CharArray.Show(10,Unsorted array is:);
20、CharArray.Sort(10);CharArray.Show(10,Sorted array is:);cout endl;第7章 模板定义了两个类模板对象,分别为定义了两个类模板对象,分别为int型和型和char型,数组元素分别被初始化为型,数组元素分别被初始化为0和空和空格格程序运行结果为:程序运行结果为:Unsortedarrayis:Unsortedarrayis:8934324715817836638389343247158178366383Sortedarrayis:Sortedarrayis:1532343647637881838915323436476378818389U
21、nsortedarrayis:Unsortedarrayis:CWrYkJXZysCWrYkJXZysSortedarrayis:Sortedarrayis:CJWXYZkrsyCJWXYZkrsy例例7.67.6使用缺省参数定义数组的类模板使用缺省参数定义数组的类模板#include using namespace std;template class ArrayT*data;int size;public:Array(int);Array();T&operator(int);第7章 模板template template Array:Array(int n)Array:Array(int
22、n)data=new Tsize=n;data=new Tsize=n;template template Array:Array()Array:Array()delete data;delete data;template template T&Array:operator(int i)T&Array:operator(int i)return datai;return datai;注意:函数模板不能定义缺省参数,而类模板却可以定义缺省参数。例例7.67.6(续)(续)voidmain(void)inti;ArrayL1(10);/等价于ArrayL1(10)ArrayL2(20);for(
23、i=0;i10;i+)L1i=i;for(i=0;i20;i+)L2i=A+i;for(i=0;i10;i+)coutL1i;coutendl;for(i=0;i20;i+)coutL2i;coutendl;第7章 模板程序运行结果为:程序运行结果为:01234567890123456789ABCDEFGHIJKLMNOPQRSTABCDEFGHIJKLMNOPQRST例例7.77.7折半查找函数模板折半查找函数模板第7章 模板基本思想:对于已按关键字排序的序列,经过一次比较,可将序列分割成两部分,然后只在有可能包含待查元素的一部分中继续查找,并根据试探结果继续分割,逐步缩小查找范围,直至找到
24、或找不到为止。比如在如下数组中查找值为48的元素:例例7.77.7(续一)(续一)template int BinSearch(T list,int n,T key)int mid,low,high;T midvalue;low=0;high=n-1;while(low=high)/low=high表示整个数组尚未查找完mid=(low+high)/2;/求中间元素的下标midvalue=listmid;/取出中间元素的值if(key=midvalue)return mid;/若找到,返回下标else if(key midvalue)high=mid-1;/若keymidvalue将查找范围缩
25、小到数组的前一半elselow=mid+1;/否则将查找范围缩小到数组的后一半return-1;/没有找到返回-1 第7章 模板例例7.77.7(续二)(续二)#includeusing namespace std;templateintBinSearch(Tlist,intn,Tkey);voidmain()inta10=2,3,7,12,16,35,67,68,90,98;charc11=abcdhijklm;charc1=f;inti=BinSearch(a,10,35);intj=BinSearch(a,10,36);intk=BinSearch(c,10,f);intl=BinSearch(c,10,k);couti,j,k,lendl;第7章 模板程序运行结果为:程序运行结果为:5,-1,-1,75,-1,-1,7 返 回例例7.87.8链表类模板链表类模板 第7章 模板基本思想:链表是以指针作为链,将若干相同类型的数据串接起来。链表在存储器中是分布式存储的,每个数据项附加指针,每个数据项只有一个指针的链表称为单向链表,本例就是一个单向链表类模板。(具体代码参见程序)谢谢!