还剩105页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
教分院(部)教研室课程名称教师姓名职称案信息学院计算机科学与技术面向对象程序设计金淑娟讲师使用教材C++语言程序设计抽象实例-一钟表数据抽象intHourintMinuteintSecond代码抽象SetTimeQShowTimeQ抽象实例——钟表类classClock{public:voidSetTimeintNewHintNewintNewS;voidShowTimeQ;private:intHourMinuteSecond;;
3.抽象实例——人数据抽象char*namechar*genderjntagejntid代码抽象生物属性角度GetClothQEat,StepQ/•社会属性角度WorkQPromoteQ/•
二、封装将抽象出的数据成员、代码成员相结合,将它们视为一个整体•用于传送字节到一个输出流对象
2.操作符1控制输出格式♦控制输出宽度-为了调整输出,可以通过在流中放入setw操纵符或调用width成员函数为每个项指定输出宽度•例11」使用width控制输出宽度#includeiostreamusingnamesoacestd;intmain{doublevaluesD={
1.
2335.
36653.
74358.24};forinti=0;i4;i++{cout.width10;coutvalues[i]*\n;例使用*填充#includeiostreamusingnamespacestd;intmainQ{doublevalues□二{
1.
2335.
36653.
74358.24};forinti=0;i4;i++{cout.width10;cout.fillf*1;coutvalues[i]\n;}}使用setw指定宽度例11-2#includeiostream#includciomanipusingnamespacestd;intmainQ{doublevaluesn={
1.
2335.
36653.
74358.24;char*names□二{“Zoot”JJimmyYATJStan”};forinti=0;i4;i++coutsetw6namcs[i]setwl0values[i]endl;输出结果Zoot
1.23Jimmy
35.36Al
653.7Stan
4358.242设置对齐方式举例说明例11-3#includeiostream#includciomanipusingnamespacestd;intmainQ{doublevaluesD={
1.
2335.
36653.
74358.24;char*names□二{“Zoot”JJimmy”JA『JStan”};forinti=0;iv4;i++coutsetiosflagsios::leftvsetw6names|i|resetiosflagsios::leftvsetwl0values|i]«endl;3)输出精度控制输出精度例11-4#includeiostream#includeiomanipusingnamespacestd;intmainQ{doublevaluesQ={
1.
2335.
36653.
74358.24};char*names[|二{Zoot”「JimmyJAIJStan};coutsetiosflagsios::scientific;forinti=0;i4;i++coutsetiosflagsios::leftsctw6namcs[i]resetiosflagsios::leftsetvr10setprecisionlvalues[i]endl;输出结果Zoot1Jimmy4e+001Al7e+002Stan4e+0034进制dec、oct和[hex操纵符设置输入和输出的缺省进制
三、输出流成员函数•输出流成员函数有三种类型与操纵符等价的成员函数执行非格式化写操作的成员函数其它修改流状态且不同于操纵符或插入运算符的成员函数open函数把流与一个特定的磁盘文件关联起来需要指定打开模式put函数把一个字符写到输出流中write函数把内存中的一块内容写到一个输出文件流中seekp和tellp函数操作文件流的内部指针close函数关闭与一个输出文件流关联的磁盘文件错误处理函数在写到一个流时进行错误处理举例向文件输出例11-5#includefstreamusingnamespacestd;structDate{intmodayr;};intmainQDatedt={61092;ofstreamtfilendate.datHios::binaty;tfile.writechar*dtsizeofdt;tfilc.closeO;
四、二进制输出文件以通常方式构造一个流,然后使用setmodc成员函数,在文件打开后改变模式使用ofstream构造函数中的模式参量指定二进制输出模式使用二进制操作符代替setmode成员函数ofsvbinary;第二节输入流、输入流类.重要的输入流类istream类最适合用于顺序文本模式输入cin是其派生类istream_withassign的对象ifstream类支持磁盘文件输入istringstream
2.输入流对象如果在构造函数中指定一个文件名,在构造该对象时该文件便自动打开ifstreammyFilefilename”iosmode;在调用缺省构造函数之后使用open函数来打开文件ifstreammyFile;〃建立一个文件流对象myFile.opennfilenameniosmode;//打开文件filenameo
二、提取运算符»提取运算符对于所有标准C++数据类型都是预先设计好的是从一个输入流对象获取字节最容易的方法iOS类中的很多操纵符都可以应用于输入流但是只有少数几个对输入流对象具有实际影响,其中最重要的是进制操纵符dec、oct和hex
三、输入流成员函数open函数把该流与一个特定磁盘文件相关联get函数的功能与提取运算符»很相像,主要的不同点是get函数在读入数据时包括空白字符第6章介绍过gedine的功能是从输入流中读取多个字符,并且允许指定输入终止字符,读取完成后,从读取的内容中删除终止字符第6章介绍过read成员函数从一个文件读字节到一个指定的内存区域,由长度参数确定要读的字节数如果给出长度参数,当遇到文件结束或者在文本模式文件中遇到文件结束标记字符时结束读取seekg函数用来设置输入文件流中读取数据位置的指针tcllg函数返回当前文件读指针的位置close函数关闭与一个输入文件流关联的磁盘文件举例1设置位置指针例11-9#includeiostream#includefstreamusingnamespacestd;intmainQ{charch;ifstreamtfilenpayroHHios::binaty|ios::nocreate;iftfile{tfile.seekg8;whilctfilc.goodO{tfile.getch;if!chbreak;coutch;}}else{coutnERROR:Cannotopenfilepayroll.Wendi;}tfile.closeQ;}举例2:文件读二进制记录例11-8#includeiostream#includefstrcam#includecstringusingnamespacestd;intmain{struct{doublesalary;charname[23J;}employee;ifstreamisnpayroHHios::binaty|ios::nocreate;ifis{is.readchar*employeesi2eofemployee;coutemployee.nameemployee.salaryendl;else{coutnERROR:Cannotopenfilepayroll.v〈endl;}is.closeQ;举例3:读文件并显示其中空格的位置例11-10#includeiostream#includcfstrcamusingnamespacestd;intmain{charch;ifstreamtfileHpayroir\ios::binaty|ios::nocreate;{whiletfile.goodO{streamposhere=tfile.tellgO;tfile.getch;ifch==*!coutn\nPositionnhereisaspace;}}else{coutnERROR:Cannotopenfilepayroir.endl;}tfile.closeO;目的是曾强安全性和简化编程,使用者不必了解具体的实现细节,而只需要通过外部接口,以特定的访问权限,来使用类的成员实现封装类声明中的{}实例classClock{public:voidSetTimeintNewHintNewMintNewS;voidShowTimeQ;private:intHourMinuteSecond;};
三、继承与派生是C++中支持层次分类的一种机制,允许程序员在保持原有类特性的基础上,进行更具体的说明实现声明派生类——第七章
四、多态性多态同一名称,不同的功能实现方式目的达到行为标识统一,减少程序中标识符的个数实现重载函数和虚函数——第八章
五、C++中的类类是具有相同属性和行为的一组对象的集合,它为属于该类的全部对象提供了统一的抽象描述,其内部包括属性和行为两个主要部分利用类可以实现数据的封装、隐藏、继承与派生利用类易于编写大型复杂程序,其模块化程度比C中采用函数更高第二节类的定义格式
一、类的声明类是一种用户自定义类型,声明形式class类名称{public:公有成员外部接口private:私有成员protected:保护型成员};1类的定义格式分为说明部分和实现部分,说明部分用来描述该类中的成员,包括数据成员和成员函数,成员函数使用来对数据成员进行操作的即“方法”,实现部分用来定义各种成员函数,描述这些成员函数如何实现队数据成员的操作2类由类头和类体两部分组成类头由关键字class和类名组成,类名是由用户定义的标识符,类头用来向便宜系统声明定义了一个新的class类型;而类体是对类的组织形式进行具体的描述,它由访问限制符privateprotectedpublic、数据成员和成员函数组成,整个类体用一对大括号括起来,完整地表达对类的描述3class允许隐藏内部成员,它依靠类定义中的3个访问限制符public\private\protected来确定隐藏的程度,它们将类体分成3个大部分4类的定义只是定义了某种类的组织形式,类似于结构体的定义,编译系统并不给class类型的每个数据成员分配具体的内存空间
二、类成员的访问控制3个访问限制符将类体分成3个大部分,每一部分都可以有数据成员和成员函数,也可以只有数据成员或只有成员函数,但不同的访问限制符规定了该部分所具有的访问权限Public公有类型的成员在关键字public后面声明,这一部分是透明的,它的数据成员和成员函数是开放的即可以由本类的成员函数直接访问,也可以由任何外部函数来访问,它们是类与外部的接口外部访问是通过“对象名•公有成员名”进行Private私有类型的成员在关键字private后面声明,这一部分象一个黑盒子,完全隐藏的它只允许本类中的成员函数直接访问既在成员函数体内直呼其名写出成员名,象日期类Date的SctDatc成员函数体内,可以直接写ayear=y;month=mday=d/等语句;而类外部的任何函数都不能访问如不允许编写成”对象名.私有成员名“形式如果紧跟在类名称的后面声明私有成员则关键字pHvate可以省略Protected保护类型成员这一部分是半透明的,与private类似,其差别表现在继承与派生时对派生类的影响不同它可由本类成员函数或它的派生类成员函数直接访问,而其它的函数不允许访问此部分
三、数据成员与一般的变量声明相同,但需要将它放在类的声明体中classClockpublic:voidSetTimeintNcwHintNcwMintNewS;//声明设置时钟的成员函数voidShowTimc;//声明显示时钟的成员函数private:intHourMinuteSecond;;voidClock::SetTimeintNewHintNewMintNcwS〃设置时钟的成员函数在类体外的实现Hour=NewH;Minute=NewM;Second=NewS;}voidClock::ShowTimeO//显示时钟的成员函数在类体外的实现coutHourvvMinuten:nSecond;通常,总是将数据成员指定为私有的,以实现数据隐藏,这些数据成员用来描述该类对象的属性,编程者无法直接访问它们而隐藏起来成员函数1)成员函数说明在类中说明原形,可以在类外给出函数体实现,并在函数名前使用类名加以限定也可以直接在类中给出函数体,形成内联成员函数允许声明重载函数和带默认形参值的函数(见上面例子中成员函数的定义)2)内联成员函数为了提高运行时的效率,对于较简单的函数可以声明为内联形式内联函数体中不要有复杂结构(如循环语句和switch语句)在类中声明内联成员函数的方式-将函数体放在类的声明中-使用inline关键字举例1classPoint(public:voidInit(intinitXintinitY){X=initX;Y=initY;)intGetXQ{returnX;}intGetYQ{returnY;}private:intXY;};举例2classPointpublic:voidInitintinitXintinitY;intGctXQ;intGetYQ;private:intXY;;inlinevoidPoint::InitintinitXintinitYX=initX;Y=initY;}inlineintPoint::GetXOreturnX;}inlineintPoint::GetYO(returnY;}一般将成员函数指定为公有的,作为该类对象访问私有数据成员的一个接口界面,即对象访问私有数据成员的一条消息通道提供给外界使用因此,一个类的对象只能通过公有成员函数访问它的私有数据成员,从而隐藏了处理这些数据的具体实现细节,使得类对数据的描述和类提供给外界来处理数据的界面互相独立,这就给出了面向对象的重要特性如日期类Date封装在一个程序实体内(定义日期类Date的程序代码),将它的私有数据成员yearmonthday等隐藏起来,不让对象随意访问,对象要访问这些私有数据成员,也只有通过公有的成员函数SetDateQIsLeapYear和PrintDatc等才能实现举例Counter类用类定义一个计数器的抽象数据类型,计数器允许的取值范围为0-4294967295的正整数,可进行的操作是计数器加
1、减1和读计数器的值数据抽象intvalue;代码抽象Counter;//给计数器赋初值Incrcament;//在计数器允许取值范围内对计数器加1Decrement;//在计数器允许取值范围内对计数器减1ReadValue;〃读计数器的值〜Counter;//撤消Counter类的对象程序实现见jsj的
11.2#include第三节对象的定义
一、对象的定义格式类的对象是该类的某一特定实体,即类类型的变量•声明形式类名对象名;例ClockmyClock;•访问对象成员——类中成员互访直接使用成员名——类外访问使用“对象名•成员名”方式访问public属性的成员类应用举例#includeiostreamusingnamespacestd;classClock……//类的声明略〃……类的实现略intmainQ{ClockmyClock;myClock.SetTime83030;myClock.ShowTimcO;
二、对象指针和对象引用的定义格式
1、对象指针•声明形式类名*对象指针名;例PointA510;Piont*ptr;ptr=A;•通过指针访问对象成员对象指针名-成员名ptr-getxQ相当于*ptr.getxQ;对象指针应用举例intmainQPointA510;Point*ptr;ptr=A;intx;x=ptr-GetXQ;coutxendl;return0;
2、对象引用•声明形式类名对象名二已存在的同类对象名;〃给已有的对象另外取一个别名例PointA;PiontB二A;•通过对象引用访问对象成员——使用“对象引用名•成员名”方式访问public属性的成员与使用对象名.成员名方式访问是等价的举例说明#includeiostreamusingnamespacestd;classClock{……//类的声明略}//……类的实现略intmainQ{ClockClockl;ClockmyClock=Clockl;//定义对象引用myClock.SctTime83030;//等同于Clockl.etTime83030;myClockShowTime;//等同于Clockl.ShowTimeQ;第四节对象的初始化
一、构造函数
1、构造函数说明构造函数的作用是在对象被创建时使用特定的值构造对象,或者说将对象初始化为一个特定的状态在对象创建时由系统自动调用如果程序中未声明,则系统自动产生出一个默认形式的构造函数允许为内联函数、重载函数、带默认形参值的函数构造函数举例classClockpublic:ClockintNewHintNewMintNewS;//构造函数voidSetTimeintNewHintNewMintNewS;voidShowTimeQ;private:intHourMinuteSecond;};构造函数的实现Clock::ClockintNewHintNewMintNewSHour=NewH;Minute=NewM;Second=NewS;}建立对象时构造函数的作用intmainQ{ClockcOQO;//隐含调用构造函数,将初始值作为实参c.ShowTimeQ;}
2、复制构造函数拷贝构造函数拷贝构造函数是一种特殊的构造函数,其形参为本类的对象引用教务处制class类名{public:类名形参;//构造函数类名类名对象名;〃拷贝构造函数•••};类名:类名类名对象名//拷贝构造函数的实现{函数体}拷贝构造函数举例1:classPointpublic:Pointintxx=0intyy=0{X=xx;Y二yy;}PointPointp;intGetXQ{returnX;}intGetYQ{returnY;}private:intXY;};Point::PointPointp{X=p.X;Y=p.Y;coutvv”拷贝构造函数被调用vvendl;复制构造函数举例2:当用类的一个对象去初始化该类的另一个对象时系统自动调用拷贝构造函数实现拷贝赋值intmainQ{PointAl2;PointBA;//拷贝构造函数被调用coutB.GetXQendl;}复制构造函数举例3:若函数的形参为类对象,调用函数时,实参赋值给形参,系统自动调用拷贝构造函数例如voidfun1Pointp{coutp.GetXQendl;}intmainQ{PointAl2;funlA;//调用拷贝构造函数复制构造函数举例4:当函数的返回值是类对象时,系统自动调用拷贝构造函数例如Pointfun2Q{PointAl2;returnA;//调用拷贝构造函数intmainQPointB;B=fun2Q;如果程序员没有为类声明拷贝初始化构造函数,则编译器自己生成一个拷贝构造函数这个构造函数执行的功能是用作为初始值的对象的每个数据成员的值,初始化将要建立的对象的对应数据成员
二、析构函数完成对象被删除前的一些清理工作在对象的生存期结束的时刻系统自动调用它,然后再释放此对象所属的空间如果程序中未声明析构函数,编译器将自动产生一个默认的析构函数构造函数和析构函数举例#includeiostreamusingnamespacestd;classPointpublic:Pointintxxjntyy;〜Point;〃…其它函数原形private:intXintY;};Point::Pointintxxintyy{X=xx;Y=yy;Point::〜Point〃…其它函数的实现略类的应用举例一圆型游泳池如图所示,现在需在其周围建一圆型过道,并在其四周围上栅栏栅栏价格为35元/米,过道造价为20元/平方米过道宽度为3米,游泳池半径由键盘输入要求编程计算并输出过道和栅栏的造价#includeiostreamusingnamespacestd;constfloatPI=
3.14159;constfloatFencePrice=35;constfloatConcretePrice=20;//声明类Circle及其数据和方法classCircleprivate:floatradius;public:Circlefloatr;//构造函数floatCircumfcrcnccQconst;//圆周长floatAreaQconst;//圆面积;//类的实现//构造函数初始化数据成员radiusCircle::Circlefloatr{radius=r}//计算圆的周长floatCircle::CircumferenceOconstreturn2*PI*radius;〃计算圆的面积floatCircle::AreaQconstreturnPI*radius*radius;voidmainQfloatradius;floatPenceCostConcreteCost;//提示用户输入半径coutnEntertheradiusofthepool:cinradius;//声明Circle对象CirclePoolradius;CirclePoolRimradius+3;//计算栅栏造价并输出FenceCost=PoolRim.CircumferenceO*FencePrice;coutFencingCostis¥FcnccCostcndl;//计算过道造价并输出ConcreteCost=PoolRim.AreaQ-Pool.AreaO*ConcretePrice;coutConcreteCostis¥ConcreteCostendl;运行结果Entertheradiusofthepool:10FencingCostisY
2858.85ConcreteCostisY
4335.39第五节对象指针和对象引用的应用
一、对象指针作为函数的参数
二、对象引用做函数的参数
三、This指针
1、This指针说明•隐含于每一个类的成员函数中的特殊指针•明确地指出了成员函数当前所操作的数据所属的对象当通过一个对象调用成员函数时,系统先将该对象的地址赋给this指针,然后调用成员函数成员函数对对象的数据成员进行操作时,就隐含使用了this指针例如Point类的构造函数体中的语句X=xx;Y=yy;相当于this-X=xx;this-Y=yy;
2、指向类的非静态成员的指针通过指向成员的指针只能访问公有成员1)声明指向成员的指针—声明指向公有数据成员的指针类型说明符类名::*指针名;—声明指向公有函数成员的指针)类型说明符(类名::*指针名)(参数表);—指向数据成员的指针(说明指针应该指向哪个成员)指针名=类名::数据成员名;2)通过对象名(或对象指针)与成员指针结合来访问数据成员对象名.*类成员指针名或对象指针名一〉*类成员指针名•指向函数成员的指针——初始化指针名二类名::函数成员名;3)通过对象名(或对象指针)与成员指针结合来访问函数成员(对象名.*类成员指针名)(参数表)或(对象指针名一〉*类成员指针名)(参数表)举例说明访问对象的公有成员函数的不同方式intmainO//主函数{PointA45;//声明对象APoint*pl=A;//声明对象指针并初始化//声明成员函数指针并初始化intPoint::*p_GetX0=Point::GetX;//1使用成员函数指针访问成员函数coutA.*p_GetX0endl;//2使用对象指针访问成员函数coutpl-GetX0endl;//3使用对象名访问成员函数coutA.GctXQcndl;}
3、指向类的静态成员的指针对类的静态成员的访问不依赖于对象•可以用普通的指针来指向和访问静态成员例6-14—通过指针访问类的静态数据成员#includeiostreamusingnamespacestd;classPoint//Point类声明{public://外部接口Pointintxx=0intyy=O{X=xx;Y=yy;countP++;}//构造函数PointPointp;//拷贝构造函数intGetXQ{returnX;}intGctYQ{returnY;}staticintcountP;〃静态数据成员引用性说明private:〃私有数据成员intXY;;Point::PointPointp{X=p.X;Y=p.Y;countP++;}intPoint::countP=0;//静态数据成员定义性说明intrnainQ//主函数{〃声明一个int型指针,指向类的静态成员int*count=Point::countP;PointA45;//声明对象Acout«HPointA/«A.GetX0«H;,«A.GetY0;//直接通过指针访问静态数据成员coutHObjectid=n*countendl;PointBA;//声明对象Bcout«HPointBn«B.GctX0«n;«B.GetY0;//直接通过指针访问静态数据成员coutHObjectid=H*countendl;例6-15—通过指针访问类的静态函数成员#includeiostreamusingnamespacestd;classPoint//Point类声明{pubHc://外部接口〃其它函数略staticvoidGetCQ//静态函数成员{coutnObjectid=ncountPendl;}private://私有数据成员intXY;staticintcountP;//静态数据成员引用性说明};//函数实现略intPoint::countP=0;//静态数据成员定义性说明intmainQ//主函数//指向函数的指针,指向类的静态成员函数void*gc0—Point::GetC;PointA45;//声明对象Acout«HPointA/«A.GetX0«n/«A.GctY0;gcQ;〃输出对象序号,通过指针访问静态函数成员PointBA;//声明对象Bcout«HPointBn«B.GetXO«n;,«B.GetYO;gcO;//输出对象序号,通过指针访问静态函数成员}
四、递归类第六节动态内存分配
一、动态申请内存操作符newnew类型名T初值列表功能在程序执行期间,申请用于存放T类型对象的内存空间,并依初值列表赋以初值结果值成功T类型的指针,指向新分配的内存失败0NULL
二、释放内存操作符deletedelete指针P功能释放指针P所指向的内存P必须是new操作的返回值例6-16动态创建对象举例#includeiostreamusingnamespacestd;classPoint{public:PointQ{X=Y二0;coutHDefaultConstructorcalled.\n;}Pointintxxjntyy{X=xx;Y=yy;coutConstructorcalled.\nn;}〜Point{coutHDestructorcalled.\nn;}intGetXQ{returnX;}intGetYQ{returnY;}voidMoveintxinty{X=x;Y=y;}private:intXY;};intmain{coutnStepOne:nendl;Point*Ptrl=ncwPoint;deletePtrl;coutHStepTwo:nendl;Ptrl=newPointl2;deletePtrl;return0;}运行结果StepOne:DefaultConstructorcalled.Destructorcalled.StepTwo:Constructorcalled.Destructorcalled.
三、浅拷贝与深拷贝•浅拷贝一实现对象间数据元素的一一对应复制•深拷贝-当被复制的对象数据成员是指针类型时,不是复制该指针成员本身,而是将指针所指的对象进行复制例6-20对象的浅拷贝参考资料(含参考书目、文献等)
1、HarveyM.Deitel及PaulJamesDeitel著,C++大学教程(第三版),电子工业出版社
2、刘正林,面向对象程序设计,华中科技大学出版社
3、周生炳等,面向对象程序设计,清华大学出版社
4、揣锦华,面向对象程序设计与VC++实践,西安电子科技大学出版社
5、王育坚编面向对象编程教程,清华大学出版社
6、王萍编著C++面向对象程序设计,清华大学出版社出版
7、徐孝凯等编,面向对象程序设计实验,中央广播电视大学出版社出版第一节面向对象的方法、面向对象的语百出发点更直接地描述客观世界中存在的事物(对象)以及它们之间的关系特点是高级语言将客观事物看作具有属性和行为的对象通过抽象找出同一类对象的共同属性和行为,形成类通过类的继承与多态实现代码重用优点使程序能够比较直接地反问题域的本来面目,软件开发人员能够利用人类认识事物所采用的一般思维方法来进行软件开发
二、程序设计方法的发展历程
1.面向过程的程序设计方法程序的目的用于数学计算主要工作设计求解问题的过程缺点对于庞大、复杂的程序难以开发和维护#includciostrcamusingnamespacestd;classPoint{//类的声明同例6-16//……;classArravOffointsJ//类的声明同例6-18//……};intmain{intnumber;cinnumber;ArrayOI-PointspointsArraylnumber;pointsArrayl.Element
0.Move510;pointsArrayl.Elementl.Movel520;ArrayOfPointspointsArray2pointsArrayl;coutnCopyofpointsArrayl:nendl;coutnPoint_0ofarray2:pointsArray
2.Element
0.GctXQnnpointsArray
2.Element
0.GetYOendl;coutHPoint_lofarray2:HpointsArray
2.Elementl.GetXQnnpointsArray
2.Elementl.GetY«endl;pointsArrayl.Element
0.Move2530;pointsArrayl.Elementl.Movc3540;coutnAfterthemovingofpointsArrayl nendl;coutHPoint_0ofarray2:npointsArray
2.Element
0.GetXO*\npointsArray
2.Element
0.GetYQendl;coutHPoint_lofarray2:HpointsArray
2.Elementl.GetX0nHpointsArray
2.Elcmcntl.GctY0cndl;}运行结果如下:Pleaseenterthenumberofpoints:2DefaultConstructorcalled.DefaultConstructorcalled.CopyofpointsArrayl:Point_0ofarray2:510Point_lofarray2:1520AfterthemovingofpointsArrayl Point_0ofarray2:2530Point_lofarray2:3540Deleting...Destructorcalled.Destructorcalled.Deleting...接下来程序出现异常,也就是运行错误用图说明浅拷贝见电子课件例6-21对象的深拷贝#includeiostreamusingnamespacestd;classPoint{//类的声明同例6-16;classArrayOfPointsJ{public:ArrayOfPointsArrayOfPointspointsArray;//其它成员同例6-18};ArrayOfPoints::ArravOfPoints,JArrayOfPointspointsArraynumbcrOfPoints=pointsArray.numbcrOfPoints;points=newPoint[numberOfPointsj;forinti=0;inumberOfPoints;i++points[i].MovepointsArray.Elementi.GetXO,pointsArray.Elementi.GetYQ;}intmainQ{//同例6-20程序的运行结果如下Pleaseenterthenumberofpoints:2DefaultConstructorcalled.DefaultConstructorcalled.DefaultConstructorcalled.DefaultConstructorcalled.CopyofpointsArray1Point_0ofarray2:510Point_lofarray2:1520AfterthemovingofpointsArrayl Point_0ofarray2:510Point_lofarray2:1520Deleting...Destructorcalled.Destructorcalled.Deleting...Destructorcalled.Destructorcalled.用图说明见电子课件第七节静态成员、静态数据成员•静态数据成员一用关键字static声明-该类的所有对象维护该成员的同一个拷贝-必须在类外定义和初始化,用::来指明所属的类举例具有静态数据成员的Point类#includeiostreamusingnamespacestd;classPoint{public:Pointintxx=0intyy=0{X=xx;Y二yy;countP++;}PointPointp;intGetXQ{returnX;}intGetY0{returnY;}voidGetCQ{coutnObjectid=ncountPendl;}private:intXY;staticintcountP;;Point::PointPointp{X=p.x;Y=P.Y;countP++;intPoint::countP=0;intmainQ{PointA45;cout«HPointAn«A.GetX0«n;,«A.GetY0;A.GetCQ;PointBA;cout«!!PointB;«B.GetXO«n;,«B.GetYO;B.GetCQ;
二、静态成员函数・静态成员函数-类外代码可以使用类名和作用域操作符来调用静态成员函数-静态成员函数只能引用属于该类的静态数据成员或静态成员函数静态成员函数举例1:#includeiostreamusingnamespacestd;classApplication{public:staticvoidfQ;staticvoidgQ;private:staticintglobal;};intApplication::global=0;voidApplication{global=5;}voidApplication::gQ{coutglobalendl;}intmainQApplication::fO;Application::gQ;return0;}举例2:classApublic:staticvoidfAa;private:intx;};voidA::fAaCOUtVVx;//对X的引用是错误的couta.x;//正确j
三、具有静态数据、函数成员的Point类#includeiostreamusingnamespacestd;classPoint//Point类声明{public://外部接口Pointintxx=0intyy=0{X=xx;Y=yy;countP++;}PointPointp;//拷贝构造函数intGetXQ{returnX;}intGctYQ{returnY;}staticvoidGetCQ{coutnObjectid=HcountPendl;}private://私有数据成员intXY;staticintcountP;Point::PointPointp{X=p.X;Y=p.Y;countP++;intPoint::countP=0;intmain〃主函数实现{PointA45;//声明对象Acout«HPointA;«A.GetX0«,,/«A.GetY0;A.GetCO;//输出对象号,对象名引用PointBA;//声明对象Bcout«nPointB;«B.GetXO«nn«B.GetYO;Point::GetC;//输出对象号类名引用第八节友元、友元的作用它是C++提供的一种破坏数据封装和数据隐藏的机制通过将一个模块声明为另一个模块的友元,一个模块能够引用到另一个模块中本是被隐藏的信息可以使用友元函数和友元类为了确保数据的完整性,及数据封装与隐藏的原则,建议尽量不使用或少使用友元
二、友元函数
1、友元函数说明友元函数是在类声明中由关键字friend修饰说明的非成员函数,在它的函数体中能够通过对象名访问private和protected成员作用增加灵活性,使程序员可以在封装和快速性方面做合理选择访问对象中的成员必须通过对象名
2、举例使用友元函数计算两点距离#includeiostream#includecmathusingnamespacestd;classPoint//Point类声明{public://外部接口Pointintxx=0intyy={X=xx;Y=yy;}intGetXQ{returnX;}intGctYQ{returnY;}friendfloatDistancePointaPointb;private://私有数据成员intXY;;doubleDistancePointaPointbdoubledx=a.X-b.X;doubledy=a.Y-b.Y;returnsqrtdx*dx+dy*dy;}intmainQ{Pointpl
3.
05.0p
24.
06.0;doubled=Distanceplp2;coutnThedistanceisndcndl;return0;;、友元类
1、友元类说明若一个类为另一个类的友元,则此类的所有成员都能访问对方类的私有成员声明语法将友元类名在另一个类中使用friend修饰说明
2、友元类举例classA{friendclassB;public:voidDisplayO{coutxendl;}private:intx;}classB{public:voidSetinti;voidDisplayO;private:Aa;};voidB::Setinti{a.x-i;voidB::DisplayQa.DisplayO;
四、友元关系是单向的如果声明B类是A类的友元,B类的成员函数就可以访问A类的私有和保护数据,但A类的成员函数却不能访问B类的私有、保护数据第九节标识符的作用域、可见性、命名空间
一、函数原型的作用域函数原型中的参数,其作用域始于,结束于例如,设有下列原型声明doubleAreadoubleradius;//radius的作用域仅在于此,不能用于程序正文其它地方因而可有可无
二、块的作用域在块中声明的标识符,其作用域自声明处起,限于块中,例如voidfuninta{intba;cinb;ifb0intc;
三、类作用域类作用域作用于特定的成员名类x的成员M具有类作用域,对M的访问方式如下-如果在X的成员函数中没有声明同名的局部作用域标识符,那么在该函数内可以访问成员Mo-通过表达式x.M或者X::M访问.面向过程的结构化程序设计方法设计思路自顶向下、逐步求精采用模块分解与功能抽象,自顶向下、分而治之程序结构按功能划分为若干个基本模块,形成一个树状结构各模块间的关系尽可能简单,功能上相对独立;每一模块内部均是由顺序、选择和循环三种基本结构组成其模块化实现的具体方法是使用子程序优点有效地将一个较复杂的程序系统设计任务分解成许多易于控制和处理的子任务,便于开发和维护缺点可重用性差、数据安全性差、难以开发大型软件和图形界面的应用软件具体有以下几点把数据和处理数据的过程分离为相互独立的实体当数据结构改变时,所有相关的处理过程都要进行相应的修改每一种相对于老问题的新方法都要带来额外的开销,程序的可重用性差图形用户界面的应用程序,很难用过程来描述和实现,开发和维护也都很困难.面向对象的方法方法将数据及对数据的操作方法封装在一起,作为一个相互依存、不可分离的整体——对象对同类型对象抽象出其共性,形成类类通过一个简单的外部接口,与外界发生关系对象与对象之间通过消息进行通讯优点程序模块间的关系更为简单,程序模块的独立性、数据的安全性就有了良好的保障通过继承与多态性,可以大大提高程序的可重用性,使得软件的开发和通过表达式prt-M0
四、文件作用域不在前述各个作用域中出现的声明,具有文件作用域,这样声明的标识符的作用域开始于声明点,结束于文件尾
五、可见性可见性是从对标识符的引用的角度来谈的概念可见性表示从内层作用域向外层作用域“看”时能看见什么如果标识在某处可见,则就可以在该处引用此标识符标识符应声明在先,引用在后如果某个标识符在外层中声明,且在内层中没有同一标识符的声明,则该标识符在内层可见对于两个嵌套的作用域,如果在内层作用域内声明了与外层作用域中同名的标识符则外层作用域的标识符在内层不可见
六、同一作用域中的同名标识符在同一作用域内的对象名、函数名、枚举常量名会隐藏同名的类名或枚举类型名重载的函数可以有相同的函数名举例#includeiostreamusingnamespacestd;inti;〃文件作用域intmainQ{i=5;inti;//块作用域=7;coutni=niendl;//输出7}coutHi=Hi;〃输出5return0;
七、对象的生存期对象从产生到结束的这段时间就是它的生存期在对象生存期内,对象将保持它的值直到被更新为止
八、静态生存期这种生存期与程序的运行期相同在文件作用域中声明的对象具有这种生存期在函数内部声明静态生存期对象,要冠以关键字static例#includeiostreamusingnamespacestd;inti=5;〃文件作用域intmain(coutHi=niendl;return0;}i具有静态生存期
九、动态生存期块作用域中声明的,没有用static修是的对象是动态生存期的对象(习惯称局部生存期对象)开始于程序执行到声明点时,结束于命名该标识符的作用域结束处例#includeiostreamusingnamespacestd;voidfunQ;intmainQ{fun;fun;voidfunQ{staticinta=l;inti=5;a++;i++;cout«Hi=i«na=naendl;例5-2变局的生存期与可见性#includciostrcamusingnamespacestd;inti=l;//i为全局变量,具有静态生存期intmainQ{staticinta;//静态局部变量,有全局寿命,局部可见intb=-10;//bc为局部变量,具有动态生存期intc=0;voidothervoid;coutnMAIN—\nn;cout«ni:Hi«na:n«anb:H«b«nc:nc«endl;c=c+8;otherQ;cout«n—MAIN—\nH;cout«ni:H«i«na:n«a«nb:H«b«Hc:H«c«endl;i=i+10;otherQ;voidothervoidstaticinta=2;staticintb;//ab为静态局部变量,具有全局寿命,局部可见//只第一次进入函数时被初始化intc=10;//C为局部变量,具有动态生存期,〃每次进入函数时都初始化a=a+2;i=i+32;c=c+5;coutOTHER—\nn;cout«ni:H«i«na:n«a«nb:H«b«nc:H«c«endl;b—a;运行结果—MAIN—i:1a:0b:-10c:0—OTHER—i:33a:4b:0c:15--MAIN―i:33a:0b:-10c:8—OTHER—i:75a:6b:4c:15例5-3具有静态、动态生存期对象的时钟程序#includeiostreamusingnamespacestd;classClock//时钟类声明{public://外部接口ClockQ;voidSetTimeintNewHintNewMintNewS;〃三个形参均具有函数原型作用域voidShowTimcQ;〜Clock{}private://私有数据成员intHourMinuteSecond;;//时钟类成员函数实现Clock::ClockO//构造函数{Hour=0;Minute=0;Second=0;voidClock::SetTimeintNewHintNewMintNewS{Hour=NewH;Minute=NewM;Sccond=NcwS;|voidClock::ShowTimeO{coutHourn:nMinuten:nSecondendl;ClockglobClock;//声明对象globClock//具有静态生存期,文件作用域intmainQ//主函数{coutFirsttimeoutput:Hendl;//引用具有文件作用域的对象globClock.ShowTimeQ;//对象的成员函数具有类作用域globClock.SetTime83030;ClockmyClockglobClock;〃声明具有块作用域的对象myClockcoutnSecondtimeoutput:nendl;myClock.ShowTimeO;//引用具有块作用域的对象程序的运行结果为:Firsttimeoutput:0:0:0Secondtimeoutput:8:30:30第十节对象数组和成员对象・、对象数组
1、对象数组的声明声明类名数组名[元素个数];访问方法通过下标访问数组名[下标].成员名
2、对象数组初始化数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象通过初始化列表赋值例PointA[2]={Pointl2Point4};如果没有为数组元素指定显式初始值,数组元素便使用默认值初始化调用默认构造函数
3、数组元素所属类的构造函数不声明构造函数,则采用默认构造函数各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数各元素对象的初值要求为不同的值时,需要声明带形参的构造函数当数组中每一个对象被删除时,系统都要调用一次析构函数
4、对象数组应用举例//Point.h#if!defined_POINT_H#define_PO1NT_HclassPoint{public:PointQ;Pointintxxintyy;^PointQ;voidMoveintxinty;intGctXQ{returnX;}intGetYQ{returnY;}private:intXY;};#cndif//6-
2.cpp#includeiostreamusingnamespacestd;#includePoint.h”Point::PointQ{X=Y=0;coutDefaultConstructorcalled.Hendl;Point::Pointintxxjntyy{X=xx;Y二yy;coutConstructorcalled.nendl;Point::〜Point{coutnDestructorcalled.nendl;}voidPoint::Moveintxinty{X=x;Y=y;}#includciostrcam#includePoint.h”usingnamespacestd;intmaincoutnEntcringmain...Hcndl;PointA
[2];forinti=0;i2;i++A[i].Movei+10J+20;coutv〈Exitingmain...nendl;return0;}运行结果Enteringmain...DefaultConstructorcalled.DefaultConstructorcalled.Exitingmain...Destructorcalled.Destructorcalled.数组中每一个元素对象被创建时,系统都会调用类构造函数初始化该对象通过初始化列表赋值例PointA
[2]={Pointl2Point34};如果没有为数组元素指定显式初始值,数组元素便使用默认值初始化调用默认构造函数数组元素属于类的构造函数不声明构造函数,则采用默认构造函数各元素对象的初值要求为相同的值时,可以声明具有默认形参值的构造函数各元素对象的初值要求为不同的值时,需要声明带形参的构造函数当数组中每一个对象被删除时,系统都要调用一次析构函数对象数组应用举例//Point.h#if!dcfined_POINT_H#define_POINT_HclassPoint{public:PointQ;Pointintxxintyy;〜Point;voidMoveintxinty;intGetXQ{returnX;}intGetYQ{returnY;}private:intXY;};#endif//6-
2.cpp#includeiostrcamusingnamespacestd;#include“Point.hPoint::PointO{X=Y=0;coutnDefaultConstructorcalled.Mcndl;}Point::Pointintxxintyy{X=xx;丫二yy;coutConstructorcalled.Hcndl;}Point::〜Point{coutnDestructorcalled.vVendl;}voidPoint::Movcintxjnty{X=x;Y=y;}#includeiostream#include“Point.h”usingnamespacestd;intmainQcoutvvEnteringmain…vVendl;PointA
[2];forinti=0;i2;i++A[i].Movci+10i+20;coutnExitingmain...nendl;return0;}运行结果Enteringmain...DefaultConstructorcalled.DefaultConstructorcalled.Exitingmain...Destructorcalled.Destructorcalled.例6-17动态创建对象数组举例#includeiostreamusingnamespacestd;classPoint{//类的声明同例6-16略};intmainQ{Point*Ptr=newPoint
[2];//创建对象数组Ptr
[0].Move510;〃通过指针访问数组元素的成员Ptr[l].Movcl520;//通过指针访问数组元素的成员维护都更为方便
三、面向对象的基本概念一般意义上的对象是现实世界中一个实际存在的事物可以是有形的(比如一辆汽车),也可以是无形的(比如一项计划)是构成世界的一个独立单位,具有•静态特征-可以用某种数据来描述•动态特征-对象所表现的行为或具有的功能.面向对象方法中的对象是系统中用来描述客观事物的一个实体,它是用来构成系统的一个基本单位对象由一组属性和一组行为构成属性-用来描述对象静态特征的数据项行为-用来描述对象动态特征的操作序列.分类所依据的原则——抽象•忽略事物的非本质特征,只注意那些与当前目标有关的本质特征,从而找出事物的共性,把具有共同性质的事物划分为一类,得出一个抽象的概念例如,石头、树木、汽车、分类——人类通常的思维方法•房屋等都是人们在长期的生产和生活实践中抽象出的概念.面向对象方法中的“类具有相同属性和服务的一组对象的集合为属于该类的全部对象提供了抽象的描述,包括属性和行为两个主要部分类与对象的关系犹如模具与铸件之间的关系,一个属于某类的对象称为该类的一个实例.面向对象方法中的“封装”把对象的属性和服务结合成一个独立的系统单元尽可能隐蔽对象的内部细节对外形成一个边界(或者说一道屏障),只保留有限的对外接口使之与外部发生联系coutHDcleting...nendl;delete[]Ptr;//删除整个对象数组return0;运行结果DefaultConstructorcalled.DefaultConstructorcalled.Deleting...Destructorcalled.Destructorcalled.例6-18动态数组类#includeiostreamusingnamespacestd;classPoint{〃类的声明同例6-16…;classArrayOfPointsJ{public:ArrayOfPointsintn{numberOfl-oints=n;points=newPoint[n];}~ArrayOfPoints{coutHDeleting...nendl;numberOfPoints=0;delete[]points;}PointElementintn{returnpoints[n];}private:Point*points;intnumbcrOfPoints;};intmainQintnumber;coutnPleaseenterthenumberofpoints:11;cinnumber;//创建对象数组ArrayOfPointspointsnumbcr;〃通过指针访问数组元素的成员points.Element
0.Move510;//通过指针访问数组元素的成员points.Elementl.Movel520;运行结果如下Pleaseenterthenumberofpoints:2DefaultConstructorcalled.DefaultConstructorcalled.Deleting...Destructorcalled.Destructorcalled.
二、成员对象和容器类教学目的及要求:了解类层次的概念及如何将概念和实现转变为类的层次的方法掌握单继承的定义格式、成员存取控制和向基类构造函数传递参数的方法教学基本内容继承,继承的类型,单继承,多继承,派生类,基类与派生类的赋值原则,虚基类重点与难点单继承的定义格式、成员存取控制和向基类构造函数传递参数的方法教学方法口讲授法M□讨论法,学指导法口其他,教学手段口多媒体M口实物口模型口挂图口音像口其他板书设计讨论、思考题、:.什么是继承,继承的作用是什么?.什么是继承方式,不同的继承方式对继承的结果有什么影响?.引用派生类后的基类对象如何进行初始化?.公有成员、受保护成员和私有成员在继承中的差别是什么?作业见书上第七章参考资料(含参考书目、文献等):
1、HarveyM.Deitel及PaulJamesDeitel著,C++大学教程(第三版),电子工业出版社
2、刘正林,面向对象程序设计,华中科技大学出版社
3、周生炳等,面向对象程序设计,清华大学出版社
4、揣锦华,面向对象程序设计与VC++实践,西安电子科技大学出版社
5、王育坚编面向对象编程教程,清华大学出版社
6、王萍编著C++面向对象程序设计,清华大学出版社出版
7、徐孝凯等编,面向对象程序设计实验,中央广播电视大学出版社出版第一节类的继承与派生
一、继承与派生的关系保持已有类的特性而构造新类的过程称为继承在已有类的基础上新增自己的特性而产生新类的过程称为派生被继承的已有类称为基类(或父类)派生出的新类称为派生类如人类(用图表示)
二、继承与派生的目的继承的目的实现代码重用派生的目的当新的问题出现,原有程序无法解决(或不能完全解决)时,需要对原有程序进行改造
三、派生类的定义.定义形式Class派生类名继承方式基类名1•二继承方式基类名n(派生类成员声明;}.直接基类和间接基类在类族中,直接参与出某类的基类叫直接基类基类的基类甚至更高层的基类称为间接基类
3、派生类的生成过程1)吸收基类成员2)改造基类成员3)添加基类的成员第二节访问控制
一、继承方式的作用不同继承方式的影响主要体现在-派生类成员对基类成员的访问权限-通过派生类对象对基类成员的访问权限
二、三种继承方式.公有继承Public•基类的public和protected成员的访问属性在派生类中保持不变,但基类的private成员不可直接访问•派生类中的成员函数可以直接访问基类中的public和protected成员,但不能直接访问基类的private成员•通过派生类的对象只能访问基类的public成员公有继承举例例7-1classPoint//基类Point类的声明{public://公有函数成员voidlnitPfloatxx=0floatyy=0{X=xx;Y=yy;}voidMovefloatxOfffloatyOff{X+=xOff;Y+=yOff;}floatGetXQ{returnX;}floatGetYQ{returnY;}private://私有数据成员floatXY;;classRectangle:publicPoint//派生类声明{public//新增公有函数成员voidInitRfloatxfloatyfloatwfloath{InitPxy;W=w;H=h;}//调用基类公有成员函数floatGetHQ{returnH;}floatGetWQ{returnW;}private:〃新增私有数据成员floatWH;;#includciostrcam#includccmathusingnamecpacestd;intmainQ{Rectanglerect;rect.InitR232010;〃通过派生类对象访问基类公有成员rect.Move32;coutrect.GetXO\!rect.GetYQ\*rect.GetHO*/rcct.GctWQcndl;return0;.私有继承private基类的public和protected成员都以private身份出现在派生类中,但基类的private成员不可直接访问派生类中的成员函数可以直接访问基类中的publicprotected成员,但不能直接访问基类的private成员通过派生类的对象不能直接访问基类中的任何成员私有继承举例例7-2classRectangle:privatePoint//派生类声明{public://新增外部接口voidInitRfloatxfloatyfloatwfloath{InitPxy;W=w;H=h;}//访问基类公有成员voidMovefloatxOfffloatyOff{Point::MovexOffyOff;floatGetXQ{returnPoint::GetXO;}floatGetYQ{returnPoint::GetY;}floatGetHQ{returnH;}floatGctWQ{returnW;}private://新增私有数据floatWH;};#includeiostream#includecmathusingnamccpaccstd;intmainQ{〃通过派生类对象只能访问本类成员Rectanglerect;rect.InitR232010;rcct.Movc32;coutrect.GetXQ*/rect.GetY0\,rect.GetH07rect.GetW0endl;return0;.保护继承protected1保护继承方式说明基类的public和protected成员都以protected身份出现在派生类中,但基类的private成员不可直接访问派生类中的成员函数可以直接访问基类中的public和protected成员但不能直接访问基类的private成员通过派生类的对象不能直接访问基类中的任何成员protected成员的特点与作用对建立其所在类对象的模块来说,它与private成员的性质相同对于其派生类来说,它与public成员的性质相同既实现了数据隐藏,又方便继承,实现代码重用protected成员举例例7-3classA{protected:intx;intmainAa;a.x=5;//错误}classA{protected:intx;classB:publicA{public:voidFunctionQ;;voidB:FunctionQx=5;//正确第三节类型兼容规则•一个公有派生类的对象在使用上可以被当作基类的对象,反之则禁止具体表现在:派生类的对象可以被赋值给基类对象派生类的对象可以初始化基类的引用指向基类的指针也可以指向派生类•通过基类对象名、指针只能使用从基类继承的成员类型兼容规则举例例7-4#includeiostreamusingnamccpaccstd;classBO//基类BO声明{public:voiddisplayO{coutHBO::displayOnendl;}//公有成员函数};classBl:publicBOpublic:voiddisplayO{coutHB1::displayQnendl;}};classDI:publicBlpublic:voiddisplayO{coutHDl::displaynendl;}};voidfunB0*ptr{ptr-displayO;对象指针-成员名”}intmainQ//主函数{BObO;//声明BO类对象Blbl;//声明Bl类对象DId1;//声明DI类对象BO*p;〃声明BO类指针p=bO;//BO类指针指向BO类对象funp;p=bl;//BO类指针指向Bl类对象funp;p=dl;//BO类指针指向DI类对象funp;运行结果
一、继承与派生的类型单继承——派生类只从一个基类派生多继承——派生类从多个基类派生多重派生——由一个基类派生出多个不同的派生类多层派生——派生类又作为基类,继续派生新的类
二、多继承时派生类的声明class派生类名继承方式1基类名1继承方式2基类名2…成员声明;注意每一个“继承方式”,只用于限制对紧随其后之基类的继承多继承举例classA{public:voidsetAint;voidshowAQ;private:inta;};classB{public:voidsetBint;voidshowBQ;private:.面向对象方法中的“继承”继承对于软件复用有着重要意义,是面向对象技术能够提高软件开发效率的重要原因之一定义特殊类的对象拥有其一般类的全部属性与服务,称作特殊类对一般类的继承例如将轮船作为一个一般类,客轮便是一个特殊类.面向对象方法中的“多态性”•多态是指在一般类中定义的属性或行为,被特殊类继承之后,可以具有不同的数据类型或表现出不同的行为这使得同一个属性或行为在一般类及其各个特殊类中具有不同的语义例如数的加法->实数的加法->复数的加法第二节面向对象的软件开发面向对象的软件工程(软件开发)是面向对象方法在软件工程领域的全面应用它包括面向对象的分析(OOA)面向对象的设计(OOD)面向对象的编程(OOP)面向对象的测试(OOT)面向对象的软件维护(OOSM)
一、系统分析系统分析阶段应该扼要精确地抽象出系统必须做什么,但是不关心如何去实现面向对象的系统分析,直接用问题域中客观存在的事物建立模型中的对象,对单个事物及事物之间的关系,都保留他们的原貌,不做转换,也不打破原有界限而重新组合,因此能够很好地映射客观事物
二、设计针对系统的一个具体实现运用面向对象的方法其中包括两方面的工作-把OOA模型直接搬到OOD作为OOD的一部分intb;};classC:publicAprivateB{public:voidsetCintintint;voidshowCO;private:intc;;voidA::setAintx{a=x;}voidB::setBintx{b=x;}voidC::setCintxintyintz{〃派生类成员直接访问基类的〃公有成员setAx;setBy;c二z;}//其它函数实现略intmainQCobj;obj.setA5;obj.showAQ;obj.setC679;obj.showCO;//obj.setB6;错误//obj.showBO;错误return0;第五节派生类的构造和析构函数
一、继承时的构造函数基类的构造函数不被继承,派生类中需要声明自己的构造函数声明构造函数时,只需要对本类中新增成员进行初始化,对继承来的基类成员的初始化,自动调用基类构造函数完成派生类的构造函数需要给基类的构造函数传递参数.单一继承时的构造函数派生类名::派生类名基类所需的形参,本类成员所需的形参:基类名参数表{本类成员初始化赋值语句;};单一继承时的构造函数举例#includeiostreamusingnamecpacestd;classB!public:BQ;Binti;〜BO;voidPrintconst;private:intb;};B::BQ{b=0;coutnBfsdefaultconstructorcalled.nendl;}B::Binti{b=i;coutnBfsconstructorcalled.Hendl;B::〜BO{coutHBsdestructorcalled.endl;}voidB::PrintQconst{coutbcndl;}classC:publicBpublic:co;Cintijntj;〜co;voidPrintQconst;private:intc;};ccq{c=0;coutHC*sdefaultconstructorcalled.nendl;C::Cintiintj:Bi{c=j;coutHCsconstructorcalled.nendl;c〜co{coutHCsdestructorcalled.nendl;}voidC::PrintOconst{B::PrintQ;coutcendl;}intmainQ{Cobj
(56);obj.PrintO;}.多继承时的构造函数派生类名::派生类名(基类1形参,基类2形参,…基类n形参,本类形参):基类名1(参数)基类名2(参数)…基类名n(参数)!本类成员初始化赋值语句;);.派生类与基类的构造函数当基类中声明有默认形式的构造函数或未声明构造函数时,派生类构造函数可以不向基类构造函数传递参数若基类中未声明构造函数,派生类中也可以不声明全采用缺省形式构造函数当基类声明有带形参的构造函数时,派生类也应声明带形参的构造函数,并将参数传递给基类构造函数.多继承且有内嵌对象时的构造函数派生类名::派生类名(基类1形参,基类2形参,…基类n形参,本类形参):基类名1(参数)基类名2(参数)…基类名n(参数),对象数据成员的初始化(本类成员初始化赋值语句;};.构造函数的调用次序1)调用基类构造函数,调用顺序按照它们被继承时声明的顺序(从左向右)2)调用成员对象的构造函数,调用顺序按照它们在类中声明的顺序3派生类的构造函数体中的内容.拷贝构造函数•若建立派生类对象时调用缺省拷贝构造函数,则编译器将自动调用基类的缺省拷贝构造函数・若编写派生类的拷贝构造函数,则需要为基类相应的拷贝构造函数传递参数例如:C::CCcl:Bcl{••.派生类构造函数举例例7-5#includeiostreamusingnamecpacestd;classBl//基类Bl构造函数有参数{public:Blinti{coutHconstructingBlHiendl;};classB2//基类B2构造函数有参数{public:B2intj{coutnconstructingB2njendl;}};classB3//基类B3构造函数无参数{public:B3{coutconstructingB3*Hendl;};classC:publicB2publicBlpublicB3public://派生类的公有成员Cintaintbintcintd:BlamemberB2dmemberBlcB2b{}private://派生类的私有对象成员BlmemberBl;B2mcmbcrB2;B3memberB3;;intmain{Cobjl234;}
二、继承时的析构函数析构函数也不被继承派生类自行声明声明方法与一般无继承关系时类的析构函数相同不需要显式地调用基类的析构函数,系统会自动隐式调用析构函数的调用次序与构造函数相反派生类析构函数举例例7-6#includeiostreamusingnamecpacestd;classBl//基类Bl声明{public:Blinti{coutnconstructingBlniendl;}~B1{coutHdestructingBlnendl;};classB2//基类B2声明{public:B2intj{coutHconstructingB2njendl;}〜B2{coutHdestructingB2nendl;}};classB3//基类B3声明{public:B3Q{coutnconstructingB3*nendl;}〜B3{coutHdestructingB3nendl;};classC:publicB2publicB1publicB3{public:Cintaintbintcintd:BlamemberB2dmemberBlcB2b{}private:BlmemberBl;B2mcmbcrB2;B3memberB3;;intmainQ{Cobjl234;}运行结构constructingB22constructingBl1constructingB3*constructingBl3constructingB24constructingB3*destructingB3destructingB2destructingBldestructingB3destructingBldestructingB2第六节派生类成员的标识与访问、同名隐藏规则当派生类与基类中有相同成员时•若未强行指名,则通过派生类对象使用的是派生类中的同名成员•如要通过派生类对象访问基类中被覆盖的同名成员,应使用基类名限定多继承同名隐藏举例(例7-7)#includciostrcamusingnamecpacestd;classBl//声明基类Bl{public://外部接口intnV;voidfuriQ{coutnMemberofBlHendl;}};classB2//声明基类B2{public://外部接口intnV;voidfunQ{coutnMcmbcrofB2cndl;}};classDI:publicBlpublicB2{public:intnV;//同名数据成员voidfunQ{coutHMemberofDlnendl;}//同名函数成员};intmainQ{DIdl;d
1.nV=l;〃对象名.成员名标识,访问D1类成员dl.funQ;dLBl::nV=2;//作用域分辨符标识,访问基类B1成员dl.Bl::funQ;d
1.B2::nV=3;//作用域分辨符标识,访问基类B2成员dl.B2::funQ;
二、二义性问题.二义性•在多继承时,基类与派生类之间,或基类之间出现同名成员时,将出现访问时的二义性(不确定性)——采用虚函数(第8章)或同名隐藏规则来解决•当派生类从多个基类派生,而这些基类又从同一个基类派生,则在访问此共同基类中的成员时,将产生二义性——采用虚基类来解决二义性问题举例
(一)classA(public:voidfQ;};classB{public:voidfQ;voidgO};classC:publicApiblicB{public:voidgO;voidhQ;};如果声明ccl;则cl.fQ;具有二义性;而cl.gO;无二义性(同名覆盖)
2.二义性的解决方法•解决方法一用类名来限定cl.A::fQ或cl.B::fQ•解决方法二同名覆盖在C中声明一个同名成员函数f,fO再根据需要调用A::fO或B::fO二义性问题举例
(二)classB{public:intb;)classBl:publicB(private:intbl;}classB2:publicB{private:intb2;};classC:publicBlpublicB2(public:intfQ;private:intd;}派生类c的对象的存储结构示意图(见电子课件)
三、虚基类
1、虚基类的引入-用于有共同基类的场合•声明以virtual修饰说明基类例class例:virtualpublicB作用针对具体实现中的人机界面、数据存储、任务管理等因素补充一些与实现有关的部分
三、编程OOP工作就是用一种面向对象的编程语言把OOD模型中的每个成分书写出来是面向对象的软件开发最终落实的重要阶段•测试的任务是发现软件中的错误•在面向对象的软件测试中继续运用面向对象的概念与原则来组织测试,以对象的类作为基本测试单位,可以更准确的发现程序错误并提高测试效率
五、维护将软件交付使用后,工作并没有完结,还要根据软件的运行情况和用户需求,不断改进系统使用面向对象的方法开发的软件,其程序与问题域是一致的,因此,在维护阶段运用面向对象的方法可以大大提高软件维护的效率-主要用来解决多继承时可能发生的对同一基类继承多次而产生的二义性问题-为最远的派生类提供唯一的基类成员,而不重复产生多次拷贝•汪思-在第一级继承时就要将共同基类设计为虚基类虚基类举例classB{private:intb;};classBl:virtualpublicB{private:intbl;};classB2:virtualpublicB{private:intb2;};classC:publicBlpublicB2{private:floatd;}下面的访问是正确的Ccobj;cobj.b;虚基类的派生类对象存储结构示意图(见电子课件7-57)虚基类举例(例7-8)(见电子课件7-5859)#includeiostreamusingnamecpacestd;classBO//声明基类BO{public://外部接口intnV;voidfunQ{coutnMemberofBOncndl;}};classBl:virtualpublicBO//BO为虚基类,派生Bl类{public://新增外部接口intnVl;};classB2:virtualpublicBO//BO为虚基类派生B2类{public://新增外部接口intnV2;};classDI:publicBlpublicB2//派生类DI声明{public://新增外部接口intnVd;voidfund{coutvvMemberofDlnendl;};intmainO//程序主函数{DIdl;//声明DI类对象dldl.nV=2;//使用最远基类成员dl.funQ;}.虚基类及其派生类构造函数建立对象时所指定的类称为最远派生类虚基类的成员是由最派生类的构造函数通过调用虚基类的构造函数进行初始化的在整个继承结构中,直接或间接继承虚基类的所有派生类,都必须在构造函数的成员初始化表中给出对虚基类的构造函数的调用如果未列出,则表示调用该虚基类的缺省构造函数在建立对象时,只有最派生类的构造函数调用虚基类的构造函数,该派生类的其它基类对虚基类构造函数的调用被忽略有虚基类时的构造函数举例#includeiostreamusingnamecpacestd;classBO//声明基类BO{public://外部接口B0intn{nV=n;}intnV;voidfunQ{coutHMemberofBOn«endl;}};classBl:virtualpublicBO{public:Blinta:BOa{}intnVl;;classB2:virtualpublicBO{public:B2inta:B0a{}intnV2;};classDI:publicBlpublicB2{public:DIinta:B0aBlaB2a{}intnVd;voidfundQ{coutHMemberofDlnendl;}};intmainQ{DIdll;dl.nV=2;dl.funQ;.综合举例•例7・10•这个程序有两点不足
①基类的成员函数pay的函数体为空,在实现部分仍要写出函数体,显得冗余
②在main函数中,建立了四个不同类的对象,对它们进行了类似的操作,但是却重复写了四遍类似的语句,程序不够简洁.空的虚函数和纯虚函数有什么区别?.纯虚函数可以实现运行时的多态性吗?怎样实现作业见书上第八章参考资料(含参考书目、文献等):
1、HarveyM.Deitel及PaulJamesDeitel著,C++大学教程(第三版),电子工业出版社
2、刘正林,面向对象程序设计,华中科技大学出版社
3、周生炳等,面向对象程序设计,清华大学出版社
4、揣锦华,面向对象程序设计与VC++实践,西安电子科技大学出版社
5、王育坚编面向对象编程教程,清华大学出版社
6、王萍编著C++面向对象程序设计,清华大学出版社出版
7、徐孝凯等编,面向对象程序设计实验,中央广播电视大学出版社出版第一节多态性的概念多态性是面向对象程序设计的重要特征之一多态性是指发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为多态的实现函数重载运算符重载虚函数问题举例——复数的运算classcomplex//复数类声明(public:complex(doubler=
0.0doublei=
0.0)//构造函数{real=r;imag=i;}voiddisplay;//显示复数的值private:doublereal;doubleimag;);•用“+”、“一”能够实现复数的加减运算吗?•实现复数加减运算的方法——重载运算符第二节运算符重载
一、运算符重载的实质.运算符重载说明•运算符重载是对已有的运算符赋予多重含义•必要性-C++中预定义的运算符其运算对象只能是基本数据类型,而不适用于用户自定义类型(如类)•实现机制-将指定的运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参-编译系统对重载运算符的选择,遵循函数重载的选择原则
2.规则和限制•可以重载C++中除下列运算符外的所有运算符*••••・•••只能重载C++语言中已有的运算符,不可臆造新的不改变原运算符的优先级和结合性不能改变操作数个数经重载的运算符,其操作数中至少应该有一个是自定义类型
3.重载的两种形式重载为类成员函数重载为友元函数
二、运算符重载声明形式函数类型operator运算符形参重载为类成员函数时,参数个数二原操作数个数-1后置++、-除外重载为友元函数时,参数个数=原操作数个数,且至少应该有一个自定义类型的形参.运算符成员函数的设计•双目运算符B-如果要重载B为类成员函数,使之能够实现表达式oprdlBoprd2其中oprdl为A类对象,则B应被重载为A类的成员函数,形参类型应该是oprd2所属的类型一经重载后,表达式oprdlBoprd2相当于oprd
1.operatorBoprd2例
8.1将运算重载为复数类的成员函数规则:-实部和虚部分别相加减操作数:-两个操作数都是复数类的对象#includeiostrcamusingnamespacestd;classcomplex//复数类声明pubHc://外部接口complexdouble『
0.0doublei=
0.0{real=r;imag=i;}〃构造函数complexoperator+complexc2;//+重载为成员函数complexoperator-complexc2;//-重载为成员函数voiddisplay;〃输出复数private:〃私有数据成员doublereal;//复数实部doubleimag;//复数虚部;complexcomplex::operator+complexc2//重载函数实现:complexc;c.real=c
2.reaH-rcal;c.imag=c
2.imag+imagreturncomplexc.realc.imag;complexcomplcx::opcrator-complexc2//重载函数实现complexc;c.real=real-c
2.real;c.imag=imag-c
2.imag;returncomplexc.rcalc.imag;}voidcomplex::displayO{coutnnrealnnimagHnendl;}intmainQ//主函数{complexcl54c2210c3;//声明复数类的对象coutncl=H;cl.display0;coutHc2=H;c
2.display0;c3=cl-c2;//使用重载运算符完成复数减法coutHc3=cl-c2=n;c
3.display;c3=cl+c2;//使用重载运算符完成复数加法coutHc3=cl+c2=n;c
3.display0;程序输出的结果为:cl=54c2=210c3=cl-c2=3-6c3=cl+c2=
7142.运算符成员函数的设计•前置单目运算符U-如果要重载u为类成员函数,使之能够实现表达式Uoprd其中oprd为A类对象,则U应被重载为A类的成员函数,无形参-经重载后,表达式Uoprd相当于oprd.operatorU0o•后置单目运算符++和---如果要重载++或-为类成员函数,使之能够实现表达式昨出++或oprd-其中oprd为A类对象,则++或-应被重载为A类的成员函数且具有一个int类型形参-经重载后,表达式oprd++相当于oprd.operator++0举例例
8.2运算符前置++和后置++重载为时钟类的成员函数前置单目运算符,重载函数没有形参,对于后置单目运算符,重载函数需要有一个整型形参操作数是时钟类的对象实现时间增加1秒钟//8_
2.cpp#includciostrcamusingnamespacestd;classClock//时钟类声明public:〃外部接口ClockintNcwH=0intNcwM=0intNcwS=0;voidShowTimcQ;Clockoperator++0;//前置单目运算符重载Clockoperator++int;//后置单目运算符重载private://私有数据成员intHourMinuteSecond;};ClockClock::operator++0//前置单目运算符重载函数{Second++;ifSecond=60{Second=Second-60;Minutc++;ifMinute=60Minute=Minute-60;Hour++;Hour=Hour%24;}return*this;〃后置单目运算符重载ClockClock::operator++int{//注意形参表中的整型参数Clockold=*this;++*this;returnold;〃其它成员函数的实现略教学基本内容类的声明,对象的定义,构造函数、析构函数,对象指针,对象引用,静态成员,友元,标识符的作用域,对象数组,成员对象,对象的存储类等重点与难点类及类对象的定义,构造函数、析构函数的定义,对象指针及对象引用的使用容器类的定义教学方法□讲授法,口讨论法,口自学指导法□其他,教学手段口多媒体M□实物口模型口挂图口音像口其他板书设计讨论、思考题.什么是类,什么是对象,类和对象是怎样的关系?.叙述静态成员和一般成员的区别.什么叫友元?什么叫友元类?什么叫友元函数?什么叫友元成员函数?.叙述友元与类的封装性之间的关系.友元方法有什么优点?有什么缺点?作业见书中第四章练习参考资料(含参考书目、文献等):
1、HarveyM.Deitel及PaulJamesDeitel著,C++大学教程(第三版),电子工业出版社
2、刘正林,面向对象程序设计,华中科技大学出版社
3、周生炳等,面向对象程序设计,清华大学出版社
4、揣锦华,面向对象程序设计与VC++实践,西安电子科技大学出版社
5、王育坚编面向对象编程教程,清华大学出版社
6、王萍编著C++面向对象程序设计,清华大学出版社出版
7、徐孝凯等编,面向对象程序设计实验,中央广播电视大学出版社出版第一节C++的面向对象的概念
一、抽象的概念抽象是对具体对象(问题)进行概括,抽出这一类对象的公共性质并加以描述的过程先注意问题的本质及描述,其次是实现过程或细节intmainQClockmyClock2355959;coutHFirsttimeoutput:;myClock.ShowTimeQ;coutnShowmyClock++:n;myClock4-4-.ShowTimeO;coutnShow++mvClock:n;Jz++myClock.ShowTime;程序运行结果为Firsttimeoutput:23:59:59ShowmvClock++:23:59:59JShow++mvClock:0:0:1J
3.运算符友元函数的设计如果需要重载一个运算符,使之能够用于操作某类对象的私有成员,可以此将运算符重载为该类的友元函数函数的形参代表依自左至右次序排列的各操作数后置单目运算符++和-的重载函数,形参列表中要增加一个吊3但不必写形参名双目运算符B重载后,表达式oprdlBoprd2等同于operatorBoprdloprd2前置单目运算符B重载后,表达式Boprd等同于operatorBoprd后置单目运算符++和-重载后,表达式oprdB等同于operatorBoprd0举例例8-3将+、-双目重载为复数类的友元函数两个操作数都是复数类的对象#includeiostreamusingnamespacestd;classcomplex//复数类声明public://外部接口complexdoubler=.Odoublei=
0.0{realnr;imag=i;}//构造函数friendcomplexoperator+complexclcomplexc2;//运算符+重载为友元函数friendcomplexoperator-complexclcomplexc2;//运算符-重载为友元函数voiddisplay;//显示复数的值private://私有数据成员doublereal;doubleimag;;complexoperator+complexclcomplexc2〃运算符重载友元函数实现{returncomplexc
2.real+cl.realc
2.imag+cl.imag;complexoperator-complexclcomplexc2//运算符重载友元函数实现{returncomplexcl.real-c
2.realcl.imag-c
2.imag;//其它函数和主函数同例
8.1第三节静态绑定与动态绑定绑定-程序自身彼此关联的过程,确定程序中的操作调用与执行该操作的代码间的关系•静态绑定静态联编-联编工作出现在编译阶段,用对象名或者类名来限定要调用的函数•动态绑定-联编工作在程序运行时执行,在程序运行时才确定将要调用的函数#includeiostreamusingnamespacestd;classPoint{public:Pointdoubleidoublej{x=i;y=j;}doubleAreaQconst{return
0.0;}private:doublexy;};classRectangle:publicPoint{public:Rectangledoubleidoublejdoublekdouble1;doubleArcaQconst{returnw*h;}private:doublewh;};Rectangle::Rectangledoubleidoublejdoublekdouble1:Pointij{w=k;h=l;}voidfunPoints{coutArea二ns.AreaQendl;}intmainQ{Rectanglerec
3.
05.
215.
025.0;funrec;运行结果Area=0#includciostrcamusingnamespacestd;classPoint{public:Pointdoublcidoublej{x=i;y=j;}virtualdoubleAreaQconst{return
0.0;}private:doublexy;};classRcctanglc:publicPoint{public:Rectangledoubleidoublejdoublekdouble1;virtualdoubleAreaconst{returnw*h;}private:doublewh;};〃其它函数同例
8.8voidfunPoints{coutArea二vs.AreaQendl;}intmainQ{Rectanglerec
3.
05.
215.
025.0;funrec;运行结果Area=375第四节虚函数、虚函数的实质虚函数是动态绑定的基础是非静态的成员函数在类的声明中,在函数原型之前写virtualovirtual只用来说明类声明中的原型,不能用在函数实现时具有继承性,基类中声明了虚函数,派生类中无论是否说明,同原型函数都自动为虚函数本质不是重载声明而是覆盖调用方式通过基类指针或引用,执行时会根据指针指向的对象的类,决定调用哪个函数举例例
8.4#includciostrcamusingnamespacestd;classBO//基类BO声明{public://外部接口virtualvoiddisplay//虚成员函数{cout«HBO::displayOnendl;};classB1:publicBO//公有派生{public:voiddisplayO{coutHB1::disphyQnendl;};classDI:publicBl//公有派生{public:voiddisplayO{coutnD1::displayQnendl;};voidfunBO*ptr//普通函数{ptr-displayQ;}intmain//主函数{BObO*p;//声明基类对象和指针Blbl;〃声明派生类对象DIdl;〃声明派生类对象p=bO;funp;〃调用基类B0函数成员p=bl;fun(p);//调用派生类Bl函数成员p=dl;fun(p);//调用派生类D1函数成员运行结果BO::displayQBl::displayODl::displayO
二、虚析构函数.何时需要虚析构函数?当你可能通过基类指针删除派生类对象时如果你打算允许其他人通过基类指针调用对象的析构函数(通过delete这样做是正常的),并且被析构的对象是有重要的析构函数的派生类的对象,就需要让基类的析构函数成为虚拟的第五节抽象类
一、纯虚函数virtual类型函数名(参数表)=0;//纯虚函数
一、抽象类作用-抽象类为抽象和设计的目的而声明,将有关的数据和行为组织在一个继承层次结构中,保证派生类具有要求的行为-对于暂时无法实现的函数,可以声明为纯虚函数,留给派生类去实现•注意抽象类只能作为基类来使用不能声明抽象类的对象构造函数不能是虚函数,析构函数可以是虚函数举例(例
8.5)#includciostrcamusingnamespacestd;classBO//抽象基类BO声明{public://外部接口virtualYoiddisplay-O//纯虚函数成员;classBl:publicBO//公有派生{public:voiddisplayO{coutHBl::disphyOnendl;}//虚成员函数};classD1:publicB1//公有派生{public:voiddisplayO{coutnD1::display0fendl;}//虚成员函数};voidfunB0*ptr//普通函数{ptr-displayQ;}intmainQ〃主函数{BO*p;//声明抽象基类指针Blbl;//声明派生类对象Didi;〃声明派生类对象p=bl;funp;//调用派生类B1函数成员p=dl;funp;〃调用派生类D1函数成员授课内容:授课时数第五章群体类和群体数据的组织4教学目的及要求掌握函数模板和类模板的作用及定义;了解各种线性群体及群体数据的组织教学基本内容:函数模板和类模板,线性群体及群体数据的组织重点和难点函数模板和类模板的作用及定义教学方法□讲授法,口讨论法,口自学指导法□其他,教学手段口多媒体,口实物口模型口挂图口音像□其他板书设计讨论、思考题、作业:.什么叫模板?什么叫函数模板?什么叫模板函数?.写出函数模板的语句格式叙述函数模板的调用方法.写出类模板的语句格式叙述类模板的调用方法.设计优先级队列类模板,并设计一个主函数进行验证.设计二叉树类模板,并设计一个主函数进行验证见书上第九章练习参考资料(含参考书目、文献等):
1、HarveyM.Dcitel及PaulJamesDeitel著,C++大学教程(第三版),电子工业出版社
2、刘正林,面向对象程序设计,华中科技大学出版社
3、周生炳等,面向对象程序设计,清华大学出版社
4、揣锦华,面向对象程序设计与VC++实践,西安电子科技大学出版社
5、王育坚编面向对象编程教程,清华大学出版社
6、王萍编著C++面向对象程序设计,清华大学出版社出版
7、徐孝凯等编,面向对象程序设计实验,中央广播电视大学出版社出版第一节模板-、函数模板•函数模板可以用来创建一个通用功能的函数,以支持多种不同形参,进一步简化重载函数的函数体设计•声明方法templatetypename标识符函数声明例求绝对值函数的模板#includeiostrcamusingnamespacestd;templatetypenameTTabsTx{returnxO-x:x;}intmainQ{intn=-5;doubled=-
5.5;cout«absnendl;coutabsdcndl;求绝对值函数的模板分析编译器从调用abs时实参的类型,推导出函数模板的类型参数例如,对于调用表达式absn由于实参n为int型,所以推导出模板中类型参数T为into•当类型参数的含义确定后,编译器将以函数模板为样板,生成一个函数:intabs(intx){returnxO-x:x;}
二、类模板.作用使用类模板使用户可以为类声明一种模式,使得类中的某些数据成员、某些成员函数的参数、某些成员函数的返回值,能取任意类型(包括基本类型的和用户自定义类型).类模板的声明•类模板template〈模板参数表class类名{类成员声明}•如果需要在类模板以外定义其成员函数,则要采用以下的形式template模板参数表》类型名类名T::函数名(参数表)•类模板应用举例(例9-2):#includeiostream#includecstdlibusingnamespacestd;//结构体StudentstructStudent{intid;//学号floatgpa;〃平均分);templateclassT//类模板实现对任意类型数据进行存取数据抽象描述某类对象的属性或状态对象相互区别的物理量代码抽象描述某类对象的共有的行为特征或具有的功能抽象的实现通过类的声明
二、抽象实例.日期抽象实例•数据抽象intYearintMonthintDay•代码抽象SetDateQ〃设置年、月、日IsLeapYear//计算某年是否为闰年ShowDate//显示年、月、日的值抽象实例一一日期类classDatepublic:voidSetDateintyintmintd;intIsLeapDateQ;voidShowDateQ;private:intYearMonthDay;;
2.钟表classStore{private:Titem;//用于存放任意类型的数据inthaveValue;〃用于标记item是否已被存入内容public:Storevoid;//默认形式无形参的构造函数TGetElcmvoid;//提取数据函数voidPutElemTx;//存入数据函数};//默认形式构造函数的实现templateclassTStoreT::Storevoid:haveValueO{}templateclassT//提取数据函数的实现TStoreT::GetElemvoid{//如果试图提取未初始化的数据,则终止程序ifhaveValue==0{coutNoitempresent!endl;exitl;}returnitem;//返回item中存放的数据templateclassT//存入数据函数的实现voidStoreT::PutElemTx{haveValue++;//将haveValue置为TRUE表示item中已存入数值item=x;//将x值存入itemintmainQ{Studentg={100023;StorcintSIS2;StoreStudentS3;StoredoubleD;Sl.PutElem3;.PutElcm-7;coutSl.GetElemQ”S
2.GetElemQendl;.PutElemg;coutThestudentidisnSS.GetElemQ.idendl;coutnRetrievingobjectD”;coutD.GetElemOendl;〃输出对象D的数据成员//由于D未经初始化,在执行函数D.GetElementO时出错第二节线性群体
一、群体的概念群体是指由多个数据元素组成的集合体群体可以分为两个大类线性群体和非线性群体线性群体中的元素按位置排列有序,可以区分为第一个元素、第二个元素等非线性群体不用位置顺序来标识元素线性群体中的元素次序与其位置关系是对应的在线性群体中,又可按照访问元素的不同方法分为直接访问、顺序访问和索引访问在本课程中只介绍直接访问和顺序访问
二、直接访问群体一数组类・静态数组是具有固定元素个数的群体,其中的元素可以通过下标直接访问-缺点大小在编译时就已经确定,在运行时无法修改•动态数组由一系列位置连续的,任意数量相同类型的元素组成-优点其元素个数可在程序运行时改变・动态数组类模板例9-39_
3.h#ifndefARRAY_CLASS#defineARRAY_CLASSusingnamespacestd;#includeiostream#includecstdlib#ifndcfNULLconstintNULL=0;#endif//NULLenumErrorType{invalidArraySizememotyAllocationErrorindcxOutOfRangc};char*errorMsg[]={InvalidarraysizeMemoryallocationerror”HInvalidindex:n;templateclassTclassArrayJ{private:T*alist;intsize;voidErrorErrorTypcerrorintbadIndex=0const;public:Arrayintsz=50;ArrayconstArrayTA;〜Arrayvoid;ArrayToperator=constArrayTrhs;Toperator[]inti;operatorT*voidconst;intListSizevoidconst;voidRcsizcintsz;
三、顺序访问群体一链表类链表是一种动态数据结构,可以用来表示顺序访问的线性群体链表是由系列结点组成的,结点可以在运行时动态生成每一个结点包括数据域和指向链表中下一个结点的指针即下一个结点的地址0如果链表每个结点中只有一个指向后继结点的指针,则该链表称为单链表单链表的结点类模板templateclassTclassNode{private:NodeT*next;public:Tdata;NodeconstTitemNodeT*ptrnext=NULL;voidInsertAfterNodeT*p;NodeT*DeleteAftervoid;NodeT*NextNodevoidconst;;在结点之后插入一个结点templateclassTvoidNodeT::InsertAfterNodeT*p//p节点指针域指向当前节点的后继节点p-next=next;next=p;〃当前节点的指针域指向p}删除结点之后的结点NodeT*NodeT::DeleteAftervoidNodeT*tempPtr=next;ifnext==NULLreturnNULL;next=tempPtr-next;returntempPtr;链表的基本操作生成结点插入结点查找结点删除结点遍历链表•清空链表链表类模板例9-6//9_
6.h#ifndefLINKEDLIST_CLASS#defincLINKEDLIST_CLASS#includeiostream#includecstdlibusingnamespacestd;#ifndefNULLconstintNULL=0;#endif//NULL#includen9_
5.hHtemplateclassTclassLinkedList{private:NodcT*front*rcar;NodcT*prevPtr*currPtr;intsize;intposition;NodeT*GetNodeconstTitemNodeT*ptrNext二NULL;voidFrceNodeNodeT*p;voidCopyListconstLinkedListTL;public:LinkedListvoid;LinkedListconstLinkedListTL;~LinkedListvoid;LinkedListToperator二constLinkedListTL;intListSizevoidconst;intListEmptyvoidconst;voidResetintpos=0;voidNextvoid;intEndOfIJstvoidconst;intCurrentPositionvoidconst;voidInsertFrontconstTitem;voidInsertRearconstTitem;voidInsertAtconstTitem;voidInscrtAftcrconstTitem;TDeleteFrontvoid;voidDeleteAtvoid;TDatavoid;voidClearListvoid;);#cndif//LINKEDLIST_CLASS
四、特殊的线性群体栈是只能从一端访问的线性群体,可以访问的这一端称栈顶,另一端称栈底栈的基本操作:初始化入栈出栈清空栈访问栈顶元素检测栈的状态(满、空)栈类模板(例9-8)//9-
8.h#ifndefSTACKCLASS#defineSTACKCLASS#includeiostream#includecstdlibusingnamespacestd;constintMaxStackSize=50;templateclassTclassStack{private:Tstacklist[MaxStackSize];inttop;public:Stackvoid;voidPushconstTitem;TPopvoid;voidClearStackvoid;TPeckvoidconst;intStackEmptyvoidconst;intStackFullvoidconst;};〃类的实现略
五、特殊的线性群体——队列队列是只能向一端添加元素,从另一端删除元素的线性群体队列的基本状态•队空-队列中没有元素•队满-队列中元素个数达到上限•一般状态-队列中有元素,但未达到队满状态例9-10队列类模板#ifndefQUEUE_CLASS#defineQUEUE.CLASS#includciostrcam#includecstdlibusingnamespacestd;constintMaxQSize=50;templateclassTclassQueue{private:intfrontrearcount;Tqlist[MaxQSize];public:Queuevoid;voidQInsertconstTitem;TQDeletevoid;voidClearQueuevoid;TQFrontvoidconst;intQLengthvoidconst;intQEmptyvoidconst;intQFullvoidconst;};//成员函数的实现略第三节群体数据的组织插入排序选择排序交换排序顺序查找折半查找教学目的及要求:了解流的概念;了解标准输入输出流对象及其它流的使用方式;了解标准输入输出流的成员函数教学基本内容流的概念、标准输入输出流对象,其它流的使用方式,标准输入输出流的成员函数重点及难点标准输入输出流对象,标准输入输出流的成员函数.教学方法口讲授法M□讨论法M口自学指导法□其他M教学手段口多媒体M□实物口模型口挂图口音像□其他板书设计讨论、思考题、作业:.什么叫流?什么叫流类?什么叫流库?.设计一个文本文件格式读文件流,并分别用get、getline成员函数和输入操作符“”把该文件流中的字符序列输入到内存变量,并在屏幕上显示这些内存变量的值.设计一个二进制文件流读/写的简单示例程序.设计一个可拷贝任意二进制文件的程序见书上第十一章练习参考资料含参考书目、文献等:1HarveyM.Deitcl及PaulJamesDeitcl著,C++大学教程第三版,电子工业出版社
2、刘正林,面向对象程序设计,华中科技大学出版社
3、周生炳等,面向对象程序设计,清华大学出版社
4、揣锦华,面向对象程序设计与VC++实践,西安电子科技大学出版社
5、王育坚编面向对象编程教程,清华大学出版社
6、王萍编著C++面向对象程序设计,清华大学出版社出版
7、徐孝凯等编,面向对象程序设计实验,中央广播电视大学出版社出版当程序与外界环境进行信息交换时,存在着两个对象,一个是程序中的对象,另一个是文件对象流是一种抽象,它负责在数据的生产者和数据的消费者之间建立联系,并管理数据的流动程序建立一个流对象,并指定这个流对象与某个文件对象建立连接,程序操作流对象,流对象通过文件系统对所连接的文件对象产生作用读操作在流数据抽象中被称为从流中提取,写操作被称为向流中插入第二节输出流
一、输出流类.最重要的三个输出流OstreamOfstrcamoOstringstreamo.输出流对象•预先定义的输出流对象cout标准输出cerr标准错误输出,没有缓冲,发送给它的内容立即被输出clog类似于cerr但是有缓冲,缓冲区满时被输出•ofstream类支持磁盘文件输出•如果在构造函数中指定一个文件名,当构造这个文件时该文件是自动打开的-ofstreammyFilenfilename\iosmode;•可以在调用默认构造函数之后使用open成员函数打开文件ofstreammyFile;//声明一个静态输出文件流对象myFile.openffilenatneHiosmode;//打开文件使流对象与文件建立联系ofstream*pmyFile=newofstream;//建立一1个动态的输出文件流对象pmyFile-opennfilenameMiosmode;//打开文件,使流对象与文件建立联系
二、插入运算符vv及操作符.插入运算符•插入运算符是所有标准C++数据类型预先设计的授课内容第一章面向对象程序设计概念授课时数6教学目的及要求了解程序设计方法的发展过程,面向对象语言的特点掌握面向对象的概念,面向对象的程序开发过程教学基本内容程序设计方法的发展过程;面向对象程序设计的基本思想及概念,面向对象程序设计的要点及开发过程重点及难点面向对象的概念,面向对象的程序开发过程教学方法口讲授法,口讨论法,口自学指导法□其他M教学手段口多媒体M口实物口模型口挂图口音像□其他板书设计讨论、思考题、作业.叙述面向对象基本思想的特点.叙述面向对象的程序设计方法与传统面向过程的程序设计方法有何不同.什么是类,什么是对象,类和对象是怎样的关系?.抽象包括哪两方面的含义?.什么是封装,它具有怎样的特点?.什么是多态?多态的实现方式及作用有哪些?.什么叫对象的封装性?什么叫信息隐藏?C++语言是怎样实现信息隐藏的?.什么叫继承?什么叫派生?.什么叫多态性?多态性主要有哪几种?.什么叫运行时的多态性?C++语言中是怎样实现运行时的多态性的?授课内容第三章继承与派生授课时数8授课内容第一章类与对象授课时数18教学目的及要求掌握类定义的方法和存取级别掌握类的成员变量和成员函数的定义和使用,以及对象的定义了解友元函数和友元类掌握构造函数和析构函数掌握静态类成员变量和成员函数的定义和使用方法掌握内联函数的定义和使用方法掌握对象指针及对象引用的使用了解容器类的定义掌握在函数中对象传递的机制授课内容第四章多态性和虚函数授课时数8教学目的及要求掌握函数重载的概念,包括重载构造函数的定义掌握运算符重载的概念掌握使用friend重载运算符的方法掌握数组下标运算符重载、运算符new和delete的定义了解定义重载某些特殊的运算符的方法,包括重载小重载、重载〉等掌握虚函数和纯虚函数的概念了解抽象类的概念了解静态和动态联编的概念教学基本内容多态性,运算符重载,同名成员函数,虚函数,纯虚函数和抽象类重点与难点函数重载和运算符重载,动态联编,虚函数和纯虚函数及抽象类教学方法口讲授法M□讨论法M口自学指导法□其他M教学手段口多媒体M口实物口模型口挂图口音像□其他板书设计讨论、思考题.什么叫运行时的多态性?滞后联编和运行时的多态性有什么关系?.什么叫虚函数?虚函数怎样实现运行时的多态性?.叙述使系统按滞后联编方式运行的虚函数的使用方法.虚函数方法和派生类对基类成员函数重载方法有哪些相同和不同之处?.虚析构函数有什么作用?.什么叫纯虚函数?什么叫抽象类?抽象类有什么用途?授课内容第六章流类库与输入/输出授课时数4。
个人认证
优秀文档
获得点赞 0