c程序设计第七章类模板与向量_第1页
c程序设计第七章类模板与向量_第2页
c程序设计第七章类模板与向量_第3页
c程序设计第七章类模板与向量_第4页
c程序设计第七章类模板与向量_第5页
已阅读5页,还剩66页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1,第七章类模板与向量,本章考核要求:1、理解类模板的概念,对比函数模版掌握类模板的特点(对类的描述、简化程序设计),达到“领会”层次。2、熟练掌握类模板的成分以及语法,能根据要求写出类模板,达到“综合应用”层次。3、理解类模板的对象,了解类模板的实例化,达到“领会”层次。4、掌握在类体外定义成员函数的一般格式,达到“简单应用”层次。5、了解类模板的派生与继承,理解模板类集成非模板和从类模板派生一个类模版两种情况,最终达到“领会”层次。6、理解向量的概念,会定义向量列表,达到”领会“层次。7、掌握定义向量使用的基本数据类型,达到“简单应用”层次。对构造类型一般性了解,达到“识记”层次。8、掌握向量容器指定位置插入和删除对象的方法,达到“简单应用”层次。9、了解向量其他的操作方法,达到“识记”层次。,2,相关知识回顾,1、函数的重载,函数重载可以使一个函数名具有多种功能,即具有多种形态,称这种特性为。,多态性,当函数的参数不同,或者参数不同时,函数可以重载。仅有函数返回值不同区分重载函数。,类型,个数,不能,有些函数重载时参数个数相同,只是类型不同,此时重载函数比较繁琐,可利用实现。,函数模板,3,2、函数模板,c+规定模板以关键字和一个形参表开头。,template,将函数模板与某个具体数据类型连用,就产生了,又称这个过程为函数模板实例化,这种形式就是类型参数化。,模板函数,另外,c+还专门定义了一个仅仅用在模板中的关键字,它的用途之一是代替template参数列表中的关键字class。,typename,函数执行时确定参数类型的函数称为模板函数。,4,2、函数模板,函数模板是不能直接执行的,需要实例化为模板函数后才能执行。,使用格式:模板函数名(实参表)(显式比较准则),或者:模板函数名(实参表)(默认方式),5,如有函数模板如下:templateTmax(Ta,Tb)if(ab)returna;elsereturnb;,m1=max(3,8);m2=max(3.6,12.5);m3=max(a,A);,m1=max(3,8);m2=max(3.6,12.5);m3=max(a,A);,则对该函数模板的使用有:,注:要想省去显式调用的麻烦,条件是由这个调用的函数参数表能够惟一地去标识出模板参数的一个集合。,在调用函数模板时,的类型决定到底使用模板的哪个版本。也就是说,模板的参数是由的参数推断出来的。,函数参数,函数,6,classPointIntintx,y;public:PointInt(inta=0,intb=0):x(a),y(b)voidsetxy(inta,intb)x=a;y=b;voidshowxy()coutx,yendl;intgetx()returnx;intgety()returny;,classPointFloatfloatx,y;public:PointFloat(floata=0,floatb=0):x(a),y(b)voidsetxy(floata,floatb)x=a;y=b;voidshowxy()coutx,yendl;floatgetx()returnx;floatgety()returny;,voidmain()PointInta(3,4);a.showxy();PointFloatb(1.2,3.4);b.showxy();,分析以下程序的结果(lt7_1a.cpp),7,classPointIntintx,y;public:PointInt(inta=0,intb=0):x(a),y(b)voidsetxy(inta,intb)x=a;y=b;voidshowxy()coutx,yendl;intgetx()returnx;intgety()returny;,classPointFloatfloatx,y;public:PointFloat(floata=0,floatb=0):x(a),y(b)voidsetxy(floata,floatb)x=a;y=b;voidshowxy()coutx,yendl;floatgetx()returnx;floatgety()returny;,分析以下程序的结果(lt7_1a.cpp),分析PointInt类和PointFloat类的异同?,类中的数据成员以及实现的操作相同,只是数据类型不同。,为了避免因为类的数据类型不同而产生的重复性设计,可以将这些数据类型从类中分离出来形成一个通用的数据类型T,为这个数据类型T设计一个操作集,就是类模板,8,将数据类型抽象出来而形成的操作集:classPointTx,y;public:Point(Ta=0,Tb=0):x(a),y(b)voidsetxy(Ta,Tb)x=a;y=b;voidshowxy()coutx,yendl;Tgetx()returnx;Tgety()returny;,9,7.1类模板,类模板使用户可以为类定义一种模式,使得类中的某些数据成员、成员函数的参数和返回值能取得任意数据类型。类模板用于实现类所需数据的类型参数化。所以类模板也称为参数化类。,10,一、类模板基础知识,1、类模板声明的一般格式:,templateclass类名类体;,classPointTx,y;public:Point(Ta=0,Tb=0):x(a),y(b)voidsetxy(Ta,Tb)x=a;y=b;voidshowxy()coutx,yendl;Tgetx()returnx;Tgety()returny;,template,例如:,模版以template关键字和一个形参表开头。,11,voidsetxy(Ta,Tb)x=a;y=b;,Point:,templateclassPointTx,y;public:Point(Ta=0,Tb=0):x(a),y(b)voidsetxy(Ta,Tb)x=a;y=b;voidshowxy()coutx,yendl;Tgetx()returnx;Tgety()returny;,voidsetxy(Ta,Tb)x=a;y=b;,voidsetxy(T,T);,template,注:在类体外面定义成员函数时,必须用template重写类模板声明!,12,注:在类体外面定义成员函数时,必须用template重写类模板声明!(P148),一般格式为:template返回类型类名:成员函数名(函数参数列表)函数体,指template的内使用class(或typename)声明的类型参数。,如上例中的:templatevoidPoint:setxy(Ta,Tb)x=a;y=b;,13,2、类模板对象,类模板不能直接使用,必须先实例化为相应的模板类,定义该模板类的对象后才能使用。,初始化类模板时,只要传给它指定的数据类型(如int,float,double等),编译器就用指定的类型代替模板参数产生相应的模板类。,用类模板定义对象的一般格式:类名对象名(构造函数实参列表)或者:类名对象名,14,例如:templateclassPointTx,y;public:Point(Ta=0,Tb=0):x(a),y(b)voidsetxy(Ta,Tb)x=a;y=b;voidshowxy()coutx,yendl;Tgetx()returnx;Tgety()returny;,voidmain()Pointa(3,4);a.showxy();Pointb(1.2,3.4);b.showxy();,15,例题:分析以下程序结果(lt7_3.cpp)#includeusingnamespacestd;templateclasssumTmsize;public:sum(Ta=0,Tb=0,Tc=0,Td=0)m0=a;m1=b;m2=c;m3=d;Ts()Tadd=0;for(inti=0;isize;i+)add+=mi;returnadd;,voidmain()sumx(1,2,3,4);sumy(a,1,-32,1);sumz(1.2,2.3,3.4,4.5);coutx.s()endl;couty.s()endl;coutz.s()endl;,16,二、类模板的派生与继承,类模板也可以继承。声明模板继承之前,必须重新声明类模板。模板类的基类和派生类都可以是模板类或者非模板类,本节只介绍其中两种情况:,1、从非模板类派生类模板,17,classPoint/非模板类protected:intx,y;public:Point(inta=0,intb=0):x(a),y(b)voidshowxy()coutx,yendl;,template/从非模板类派生类模板classLine:publicPointTx2,y2;public:Line(inta,intb,Tc,Td):Point(a,b)x2=c;y2=d;voidsetline(inta,intb,Tc,Td)x=a;y=b;x2=c;y2=d;voidshowLine()coutPoint1坐标:;showxy();coutPoint2坐标:;coutx2,y2endl;Tlength()returnsqrt(x2-x)*(x2-x)+(y2-y)*(y2-y);,voidmain()Linea(1,1,1,3);a.showLine();coutb(1,1,1.0,5.8);coutb线段长度:b.length()endl;,18,2,从类模板派生一个类模板类模板使用时,须指出类模板的参数给出类模板参数后得到一个模板类继承后成员的访问权限变化同一般类的继承,19,classPoint/非模板类protected:intx,y;public:Point(inta=0,intb=0):x(a),y(b)voidshowxy()coutx,yendl;,template/从非模板类派生类模板classLine:publicPointTx2,y2;public:Line(inta,intb,Tc,Td):Point(a,b)x2=c;y2=d;voidsetline(inta,intb,Tc,Td)x=a;y=b;x2=c;y2=d;voidshowLine()coutPoint1坐标:;showxy();coutPoint2坐标:;coutx2,y2endl;Tlength()returnsqrt(x2-x)*(x2-x)+(y2-y)*(y2-y);,template,/类模板,/从类模板派生类模板,voidmain()Pointa(3.5,6.8);a.showxy();Lineab(4,5,6,7);ab.showLine();coutac(1.5,2.5,4.5,6.5);ac.showLine();coutac线段长度:ac.length()endl;,20,类模板总结,类模板的定义格式类模板的成员函数定义在类体外时注意事项类模板如何产生一个模板类并定义对象类模板与函数模板不同之处:类模板无法从构造函数的参数中判断出T的类型,必须显式给出模板的参数。类模板的派生类模板继承普通类,类模板派生类模板,21,课程回顾,1.如果一个模板声明列出多个参数,则多个参数之间必须使用逗号隔开,每个参数都必须重复使用关键字_。,classs,22,数组:用于存放相同类型的数据;通过数组元素使用;数组一旦定义,其大小即固定不变;可使用泛型算法。,7.2向量与泛型算法,向量是C+中一维数组的类版本,它与数组相似,其中的元素是连续存储的,不同的是:向量中存储元素的多少可以在运行中根据需要动态地增长或缩小。,向量:用于存放多个相同类型的数据;利用对象使用;可动态指定向量中元素的个数;提供了多个成员函数以方便数据使用;可使用泛型算法。,23,一、定义向量列表,是C+中的类模板。使用时加头文件vector。,向量的声明形式:(以下形式中length表示长度,type表示类型,name表示向量对象名),1)vectorname;/定义type的向量空表,没有元素,2)vectorname(length);/定义具有lengh个type的向量,元素初始化为0,3)vectorname(length,n);/定义具有lengh个type的向量,元素初始化为n,4)vectorname(name1);/使用已定义的向量name1构造向量name,5)vectorname(a,a+长度);/将已经定义好的数组a的内容复制给向量,24,向量的定义形式:1)vectorname;2)vectorname(length);3)vectorname(length,n);4)vectorname(name1);5)vectorname(a,a+length);,例题:1)定义字符型空向量A,2)定义5个int型向量B,元素初始化为0,3)定义10个int型向量C,元素初始化为3,vectorA;,vectorB(5);,vectorC(10,3);,4)用向量C构造向量D,vectorD(C);,5)定义5个字符型向量E,并初始化为a,D=B,vectorE(5,a);,6)将B赋值给D,同类型的向量可以相互赋值,而不管它们的长度如何。向量可以改变赋值目标的大小,使它的元素数目与赋值源的元素数目相同。,25,向量的定义形式:1)vectorname;2)vectorname(length);3)vectorname(length,n);4)vectorname(name1);5)vectorname(a,a+length);,例题:7)若已有数组定义如下:inta5=1,2,3,4,5;则:把数组中的全部元素复制到向量F中,vectorF(a,a+5);,26,向量的声明形式:,27,向量的使用:由vector定义的对象C+中称为向量同类型向量可相互赋值,不同类型不可相互赋值同类向量长度不同也可相互赋值向量中的元素使用类似数组元素,可使用向量名下标向量具有成员函数size()可得到向量长度,28,例题:补全程序并分析程序结果(lt7_6a.cpp)#include#includeusingnamespacestd;voidmain()inta=1,2,3,4,5;vectorF(a,a+3);cout有F.size()个元素,分别为:endl;for(inti=0;iF.size();i+)coutFi;coutendl;,向量具有成员函数size()可得到向量长度,向量中的元素使用类似数组元素,可使用向量名下标的形式,29,向量的使用(分析以下程序段得结果),30,二、泛型指针,与操作对象的数据类型相互独立的算法称为。,泛型算法,1、向量成员函数begin(),end(),rbegin(),rend()其含义为:,begin()表示向量中首元素的地址end()表示最后一个元素的下一个地址rbegin()表示向量中最后一个元素的地址rend()表示首元素的前一个地址,若有:intx=1,2,3,4,5;vectora(x,x+5);,31,特别注意向量的成员函数begin()+1表示下一个地址end()-1表示前一个地址rbegin()+1表示前一个地址rend()-1表示下一个地址,32,例题:用begin(),end(),rbegin(),rend()函数输出向量元素。(lt7_6b.c),按要求填空,#include#includeusingnamespacestd;voidmain()inta=1,2,3,4,5;vectorF(a,a+5);cout向量F有F.size()个元素,分别为:endl;for(inti=0;iF.size();i+)/正向输出向量中的元素cout*(F.begin()+i);coutendl;,输出向量元素的个数,33,若有向量定义:vectorF(a,a+5),for(inti=0;iF.size();i+)/正向输出向量中的元素cout*(F.begin()+i);coutendl,for(inti=0;iF.size();i+)/正向输出向量中的元素cout*(F.rend()-i-1);coutendl,for(inti=0;iF.size();i+)/逆向输出向量中的元素cout*(F.end()-1-i);coutendl,for(inti=0;iF.size();i+)/逆向输出向量中的元素cout*(F.rbegin()+i);coutendl,34,2、利用普通指针指向向量元素,向量成员函数begin(),end(),rbegin(),rend()可以取得向量中某个元素地址指针可以存放地址,用指针可以指向向量中的元素,注意:指针类型必须同要指向的数据类型一致,如有:vectorv(10,1);int*p;,则:p=v.begin();/指针p指向了v中的首元素,若使p指向尾元素可使用语句:,p=v.end()-1;,注意:只能用正向指针来赋值,而不能用逆向指针赋值。,如:p=v.rbegin()或者p=rend()都是错误的。,35,例题:用普通指针输出向量元素(lt7_6c.cpp)若有向量定义:inta=1,2,3,4,5;vectorv(a,a+5);int*p;,for(p=v.begin();pv.end();p+)/正向输出向量中的元素cout*p;cout=v.begin();p-)/逆向输出向量中的元素cout*p;coutendl;,36,3、泛型指针,类模板vector中提供了一个通用指针iterator,如果用T表示向量的参数化数据类型,iterator相当于T*。,注意:泛型指针是使用类实现的该指针可指向向量中的元素可使用*p表示它指向的元素值只能用正向指针给p赋值,如begin()、end()。,1)用iterator声明正向泛型指针的形式:vector:iterator指针名,例如:vector:iteratorp;表示定义了一个指向int型向量的指针p,37,用iterator声明正向泛型指针的形式:vector:iterator指针名,例题:如有向量定义vectorv(5,9);则:,定义一个可以指向向量v的指针p应使用语句:,vector:iteratorp;,使p指向向量v的首元素,可使用语句:,p=v.begin();,for(inti=0;iv.size();i+)/正向输出向量中的元素cout*(p+i)=v.begin;p-)/逆向输出向量中的元素cout*p;,38,练习:补全程序并分析运行结果(lt7_6d.cpp)#include#include#includeusingnamespacestd;voidmain()chars=happy;vectorv(s,s+strlen(s);vector:iteratorp;/定义一个指向v的向量指针pp=v.begin();for(inti=0;i=v.begin();p-)cout*p;coutendl;,39,1)对向量的访问可以是双向的。用reverse_iterator声明逆向泛型指针的形式:vector:reverse_iterator指针名,注意:如此定义的指针只能由逆向指针rbegin()和rend()赋值.,40,例题:分析如下程序的运行结果(lt7_6d2.cpp)#include#include#includeusingnamespacestd;voidmain()chars=happy;vectorv(s,s+strlen(s);vector:reverse_iteratorp;cout=v.rbegin();p-)cout*p;coutendl;cout逆向字符串:endl;for(p=v.rbegin();p=v.rend();p+)cout*p;coutendl;,41,特别注意(总结)向量不是数组!向量名不是数组名,不表示地址!也不可使用不可使用如此形式!,42,特别注意(总结)向量的成员函数begin()+1,表示下一个地址end()-1表示前一个地址rbegin()+1表示前一个地址rend()-1表示下一个地址,43,特别注意:(总结)普通指针变量和iterator指针变量(如int*p;或者vector:iteratorp;)只能被赋值为begin(),end()p=c.begin()正确p=c.end()正确p=c.rbegin()此形式错误!p=c.rend()此形式错误!,44,特别注意:(总结)逆向泛型指针变量如(如vector:reverse_iteratorp;)只能被赋值为rbegin(),rend()p=c.rbegin()正确p=c.rend()正确p=c.begin()此形式错误!p=c.end()此形式错误!,45,1、数组内容反转reverse(a,a+Len),2、1)复制数组的内容copy(a,a+Len,b),2)反向复制数组的内容reverse_copy(a,a+Len,b),3、将数组内容按升序排序sort(a,a+Len),4、1)正向输出数组的内容copy(a,a+Len,ostream_iterator(cout,”字符串”),回顾常用的泛型算法:,三、向量的数据类型,46,4、2)反向输出数组的内容reverse_copy(a,a+Len,ostream_iterator(cout,”字符串”),注:以上几个函数:reverse、copy、reverse_copy、sort以及copy和reverse_copy用于屏幕输出在使用时,应加对应的头文件。,即在程序头使用:#include,47,5、将数组内容按降序排序sort(a,a+Len,greater(),6、查找数组内容find(a,a+Len,value),注:使用以上两个函数时还需要加对应的头文件。,即在程序头使用:#include#include,48,三、向量的数据类型,向量不仅可以存取int,double等普通数据类型,也可存储对象,结构体、指针等,49,综合练习,#include/综合实例lt7_7a.cpp#include#include#includeusingnamespacestd;voidmain()inta=1,4,3,2;vectorva(a,a+4),vb(4);copy(va.begin(),va.end(),ostream_iterator(cout,);cout(cout,);cout(cout,);cout(cout,);cout(cout,);cout();copy(va.begin(),va.end(),ostream_iterator(cout,);coutendl;,50,voidmain()inta=1,4,3,2;vectorva(a,a+4),vb(4);copy(va.begin(),va.end(),ostream_iterator(cout,);cout(cout,);cout(cout,);cout(cout,);cout(cout,);cout();copy(va.begin(),va.end(),ostream_iterator(cout,);coutendl;,1432,2341,1234,4321,4321,1432,51,例题:使用结构做为向量元素(lt7_8a.cpp)#include#includeusingnamespacestd;structstruinta;doubleb;x=1,2.2,3,4.4;voidmain()vectorvs(2);/结构指针作为向量的数据类型for(inti=0;iabv(2);for(inti=0;ireal()imag()endl;,53,例题:类作为向量元素(lt7_8c.app)#include#include#includeusingnamespacestd;classpersonstringname;charsex;intage;public:person(strings=未命名,charc=X,intn=0)name=s;sex=c;age=n;voidset(strings,charc,intn)name=s;sex=c;age=n;voidshow()cout姓名:namet性别:“sext年龄ageendl;,voidmain()vectorper(3);per0.set(张三,F,30);per1.set(李四,M,40);per2.set(王五,M,35);for(inti=0;i3;i+)peri.show();,54,1、访问向量容量信息的方法size(),max_size(),capacity(),empty()用于得到当前向量的大小信息,四、向量最基本的操作方法,向量有许多成员函数提供不同的操作。,1)size():返回当前向量中已经存放的对象的个数。,2)max_size():返回向量可以容纳的最多对象的个数。,3)capacity():返回无需再次分配内存就能容纳的对象的个数。当存放空间已满,又增加一个元素时,它在原来的基础上自动翻倍扩充空间,以便存放更多的元素。,4)empty():测试向量是否为空,为空时返回true。,55,例题(lt7_9a.cpp)#include#includeusingnamespacestd;voidmain()coutv0;coutv1(5);coutv2(3,5);coutv2.size()tv2.max_size()t“v2.capacity()tv2.empty()endl;v2=v1;coutv2.size()tv2.max_size()t“v2.capacity()tv2.empty()endl;,56,2、访问向量中对象的方法,1)front():返回向量中的第一个元素,2)back():返回向量中的最后一个元素,3)operator(n):返回向量中下标为n的元素,57,例题:分析以下程序的运行结果(lt7_9.cpp)#include#includeusingnamespacestd;voidmain()chars=abcdef;vectorvs(s,s+strlen(s);coutfirstis:vs.front()endl;coutlastis:vs.back()endl;for(inti=0;ivs.size();i+)coutvs.operator(i);coutendl;,58,3、在向量中插入对象的方法,1)push_back(constTcharsex;intage;public:person()voidset()voidshow()coutv(per,per+3);cout共有v.size()个人endl;cout可以存放v.capacit

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论