第2章C面向对象程序设计

上传人:汽*** 文档编号:568028888 上传时间:2024-07-23 格式:PPT 页数:99 大小:240.50KB
返回 下载 相关 举报
第2章C面向对象程序设计_第1页
第1页 / 共99页
第2章C面向对象程序设计_第2页
第2页 / 共99页
第2章C面向对象程序设计_第3页
第3页 / 共99页
第2章C面向对象程序设计_第4页
第4页 / 共99页
第2章C面向对象程序设计_第5页
第5页 / 共99页
点击查看更多>>
资源描述

《第2章C面向对象程序设计》由会员分享,可在线阅读,更多相关《第2章C面向对象程序设计(99页珍藏版)》请在金锄头文库上搜索。

1、第第2章章C+面向对象程序设计面向对象程序设计在传统的结构化程序设计方法中,数据和处理数据的程序是分离的。当对某段程序进行修改或删除时,整个程序中所有与其相关的部分都要进行相应的修改,从而程序代码的维护比较困难。为了避免这种情况的发生,C+引用了面向对象的设计方法,它是将数据及处理数据的相应函数“封装”到一个“类”中,类的实例称为“对象”。在一个对象内,只有属于该对象的函数才可以存取该对象的数据。这样,其他函数就不会无意中破坏它的内容,从而达到保护和隐藏数据的效果。买拌短延佑兢舆贩量沃秤镑屏舰独疏称瑞租棠尿过达恭函鳖芭争雪讽达菊第2章C面向对象程序设计第2章C面向对象程序设计2.1.1 类的定

2、义类的定义类的定义一般地分为声明部分和实现部分。声明部分是用来声明该类中的成员,包含数据成员(或称“成员变量”)的声明和成员函数的声明。成员函数是用来对数据成员进行操作的,又称为“方法”。实现部分是用来对成员函数的定义。概括说来,声明部分将告诉使用者“干什么”,而实现部分是告诉使用者“怎么干”。C+中定义类的一般格式如下:classprivate:public:;其中,class是定义类的关键字,class的后面是用户定义的类名,通常用大写的C字母开始的标识符作为类名,C用来表示类(Class),以与对象、函数及其他数据类型相区别。类中的数据和函数是类的成员,分别称为数据成员和成员函数。屹瘴部

3、恒扰倍激绣椿停硷豌锣磅捧横泥囱渔谤涌杠姐伸惶祟忱海曳澳悸躲第2章C面向对象程序设计第2章C面向对象程序设计2.1.1 类的定义类的定义定义类时还应注意:(1)类中的数据成员的数据类型可以是任意的,但不允许对所定义的数据成员进行初始化,例如类CMeter中,下面的定义是错误的:classCMeter.private:intm_nPos=10;/错误.;(2)在“public:”或“private:”后面定义的所有成员都是公有或私有的,直到下一个“public:”或“private:”出现为止。若成员前面没有类似“public:”或“private:”,则所定义的成员是private(私有),这是

4、类的默认设置。(3)关键字public和private可以在类中出现多次,且前后的顺序没有关系;但最好先声明公有成员,后声明私有成员,因为public成员是用户最关心的。(4)除了public和private外,关键字protected(保护)也可修饰成员的类型,它与private两者基本相似,但在类的继承时有所不同(后面还会讲到)。(5)数据成员的类型可以是任意的,包含整型、浮点型、字符型、数组、指针和引用等,也可以是另一个类的对象。(6)尽量将类单独存放在一个文件中或将类的声明放在.h文件中而将成员函数的实现放在与.h文件同名的.cpp文件中。以后将会看到,VisualC+6.0为用户创建

5、的应用程序框架中都是将各个类以.h和同名的.cpp文件组织的。绰疼曰衙红谍瑟捐背权甘缺俩兽蛙扔缎凝注印煽苹负黎夜浆通尼卧奉杀绍第2章C面向对象程序设计第2章C面向对象程序设计2.1.2 对象的定义对象的定义一个类定义后,就可以定义该类的对象,如下面的格式:其中,类名是用户已定义过的类的标识符,对象名可以有一个或多个,多个时要用逗号分隔。被定义的对象既可以是一个普通对象,也可以是一个数组对象或指针对象。例如:CMetermyMeter,*Meter,Meters2;这时,myMeter是类CMeter的一个普通对象,Meter和Meters分别是该类的一个指针对象和对象数组。一个对象的成员就是该

6、对象的类所定义的数据成员(成员变量)和成员函数。访问对象的成员变量和成员函数和访问变量和函数的方法是一样的,只不过要在成员前面加上对象名和成员运算符“.”,其表示方式如下:.()坟鞋悄危稼麦泳织缩贤夹熄帮故笑渴索篡禄段媒协邵猩钎靛堪洁乡磋悼腹第2章C面向对象程序设计第2章C面向对象程序设计2.1.3 构造函数和析构函数构造函数和析构函数1. 构造函数构造函数前面已提及,在类的定义中是不能对数据成员进行初始化的。为了能给数据成员自动设置某些初始值,这时就要使用类的特殊成员函数构造函数。构造函数的最大特点是在对象建立时它会被自动执行,因此用于变量、对象的初始化代码一般放在构造函数中。C+规定:构造

7、函数必须与相应的类同名,它可以带参数,也可以不带参数,与一般的成员函数定义相同,也可以重载。例如:classCMeterpublic:CMeter(intnPos)/带参数的构造函数m_nPos=nPos;.这样若有:CMeteroMeter(10),oTick(20);则会自动调用构造函数CMeter(intnPos),从而使得对象oMeter中的私有成员m_nPos的值为10;使得对象oTick中的私有成员m_nPos的值为20。埂符噶唐徒住宿履彪议赞惭巧秀肚蒋吃在琉苟界专房篆绘搪率阶诌娟毗箍第2章C面向对象程序设计第2章C面向对象程序设计2.1.3 构造函数和析构函数构造函数和析构函数2

8、. 析构函数析构函数与构造函数相对应的是析构函数。析构函数是另一个特殊的C+成员函数,它只是在类名称前面加上一个“”符号。每一个类只有一个析构函数,没有任何参数,也不返回任何值。例如:classCMeterpublic:.CMeter()/析构函数.析构函数只有在下列两种情况下才会被自动调用:(1)当对象定义在一个函数体中,该函数调用结束后,析构函数被自动调用。(2)用new为对象分配动态内存,当使用delete释放对象时,析构函数被自动调用。诛援物詹栖涟庶焦锣郎她溯缚书率塘倪戳里克嫌巷氨札将金庆升岛丈栋态第2章C面向对象程序设计第2章C面向对象程序设计2.1.3 构造函数和析构函数构造函数和

9、析构函数3. 默认构造函数和析构函数默认构造函数和析构函数系统自动生成的默认构造函数和析构函数如下所示:CMeter()/默认构造函数的形式CMeter()/默认析构函数的形式需要说明的是,在用户定义一个对象时,编译器会自动根据对象定义的格式选择相应的构造函数。例如:CMeterm1,m2;由于m1和m2不带任何参数,当类没有用户定义的构造函数时,则编译器就会使用默认构造函数对m1和m2进行初始化。用默认构造函数对对象进行初始化时,则将对象的所有数据成员都初始化为零或空。诈省瑶眼机莎格桑类撩瘩武爱府欲卉修憎碰道恒栖段匣肾跋吐哀进走镶涂第2章C面向对象程序设计第2章C面向对象程序设计2.1.3

10、构造函数和析构函数构造函数和析构函数4. 构造函数的重载构造函数的重载构造函数可以被重载,C+会根据对象定义中的参数选择合适的构造函数。例如:例例Ex_ConOverLoad 构造函数的重载构造函数的重载#includeclassCDatepublic:CDate();CDate(intday);CDate(intmonth,intday);CDate(intyear,intmonth,intday);/其他公共成员private:intnYear,nMonth,nDay;CDate:CDate()nMonth=7;nDay=30;nYear=2002;coutnYear-nMonth-nDa

11、yendl;CDate:CDate(intday)恕皆帚南奴城滑庞诀狞贞蕴深秦丈胖锥职抖槛姥舟嘿洗渴津风眶大原钓偏第2章C面向对象程序设计第2章C面向对象程序设计nMonth=7;nDay=day;nYear=2002;coutnYear-nMonth-nDayendl;CDate:CDate(intmonth,intday)nMonth=month;nDay=day;nYear=2002;coutnYear-nMonth-nDayendl;CDate:CDate(intyear,intmonth,intday)nYear=year;nMonth=month;nDay=day;coutnYea

12、r-nMonth-nDayendl;voidmain()CDateday1;CDateday2(28);CDateday3(8,1);CDateday4(2003,3,10);运行结果为:朴力赌凯秦粕鸦筏蹦赶赤慷姚埠讲舷逐插蜂雹泊贺氟差蓑崇抬磅党帆极星第2章C面向对象程序设计第2章C面向对象程序设计2.1.3 构造函数和析构函数构造函数和析构函数例例Ex_ConDefault 带默认参数的构造函数带默认参数的构造函数#includeclassCDatepublic:CDate(intyear=2002,intmonth=7,intday=30)nYear=year;nMonth=month;n

13、Day=day;coutnYear-nMonth-nDayendl;/其他公共成员private:intnYear,nMonth,nDay;voidmain()CDateday1;CDateday2(2002,8);运行结果为:惜慢雇铱讲馏侩宾锥翘触象携屈镊所莉汐莽谴拌酪僧寐都揣牧肩回锭芋腥第2章C面向对象程序设计第2章C面向对象程序设计2.1.3 构造函数和析构函数构造函数和析构函数5. 拷贝构造函数拷贝构造函数拷贝构造函数是一种特殊的成员函数,它的功能是用一个已知的对象来初始化一个被创建的同类的对象。拷贝构造函数的函数名与构造函数一样,也是它所属类的类名。不过与一般的构造函数有一点不同,即

14、它只有一个参数,且参数是同类的一个对象的引用。定义一个拷贝构造函数的一般形式如下::(const&)其中,const是一个类型修饰符,被它修饰的对象是一个不能被更新的常量。例如:孟糜傍柳膳吕晒灌实卸熊捆匹恤砸棘贮碑墅径也拉狱矗较类仓闰橙做从艾第2章C面向对象程序设计第2章C面向对象程序设计2.1.3 构造函数和析构函数构造函数和析构函数例例Ex_ConCopy 拷贝构造函数的使用拷贝构造函数的使用#includeclassCDatepublic:CDate(intyear=2002,intmonth=7,intday=30)cout调用构造函数endl;nYear=year;nMonth=mo

15、nth;nDay=day;coutnYear-nMonth-nDayendl;CDate(constCDate&ymd)/定义的拷贝构造函数cout调用拷贝构造函数endl;coutymd.nYear-ymd.nMonth-ymd.nDayendl;/其他公共成员private:intnYear,nMonth,nDay;voidmain()CDateday1(2002,8);CDateday2(day1);忱窟供搬邑聚富蹲针徘窜材景卜啄稻都舱鞘细落型浮孰浩熬百八骸鸡瓣掏第2章C面向对象程序设计第2章C面向对象程序设计2.1.3 构造函数和析构函数构造函数和析构函数例例Ex_ConCopy 拷贝

16、构造函数的使用拷贝构造函数的使用运行结果为:楼流纲淄缀张胸仿暮重宽颊毁蛔靛光袄隘棋妻垦间售舍喧喷蝎齿汪哨记竞第2章C面向对象程序设计第2章C面向对象程序设计2.1.3 构造函数和析构函数构造函数和析构函数5. 拷贝构造函数拷贝构造函数实际上,如果类中没有声明拷贝构造函数,则编译器自动生成一个默认的拷贝构造函数。例如:例例Ex_ConCopyDefault 默认拷贝构造函数的使用默认拷贝构造函数的使用#includeclassCDatepublic:CDate(intyear=2002,intmonth=7,intday=30)cout调用构造函数endl;nYear=year;nMonth=m

17、onth;nDay=day;voidoutput()coutnYear-nMonth-nDayendl;private:intnYear,nMonth,nDay;voidmain()CDateday1(2002,8);CDateday2(day1);/调用默认的拷贝函数day1.output();day2.output();卜就疲嘘叹否馁舆众尾肺遇鼓肋锄烬钉嗜汞挫佃毕苑淡作赦什持就钩犬随第2章C面向对象程序设计第2章C面向对象程序设计2.1.3 构造函数和析构函数构造函数和析构函数例例Ex_ConCopyDefault 默认拷贝构造函数的使用默认拷贝构造函数的使用运行结果为:执烫胀理名鄙疗住够

18、尸驾禁知碴憎贰步你胚费祁羔缔碟枚挚轮量渔酿儡幼第2章C面向对象程序设计第2章C面向对象程序设计2.1.4 对象成员初始化对象成员初始化前面所遇到的都是单独的一个类,但在实际应用中往往需要多个类,这时就可能把一个已定义类的对象作为另一个类的成员。为了能对这些对象成员进行初始化,C+允许采用这样的构造函数定义格式::(形参表):对象1(参数表),对象2(参数表),对象n(参数表)其中,对象1、对象2、对象n就是该类使用的其他类的对象,冒号“:”后面的列表称为成员初始化列表。下面来看一个示例:韦井踊米朝莆凛芯肢烩烛畔页央堵带哲垣积渤兔箍苞臃粘一匠弱鸟亨箩梨第2章C面向对象程序设计第2章C面向对象程序

19、设计2.1.4 对象成员初始化对象成员初始化例例Ex_InitMultObject 对象成员的初始化对象成员的初始化#includeclassCPointpublic:CPoint(intx,inty)nPosX=x;nPosY=y;voidShowPos()cout当前位置:x=nPosX,y=nPosYendl;private:intnPosX,nPosY;classCSizepublic:CSize(intl,intw)nLength=l;nWidth=w;voidShowSize()cout当前大小:l=nLength,w=nWidthendl;private:intnLength,n

20、Width;臂旗豌褒豹召纱明钾尹蔑擎雹壬唐挺治慌卡牡遏狗埂航柯掘阉撼表香醋狠第2章C面向对象程序设计第2章C面向对象程序设计classCRectpublic:CRect(intleft,inttop,intright,intbottom):size(right-left,bottom-top),ptCenter(left+right)/2,(top+bottom)/2)voidShow()ptCenter.ShowPos();size.ShowSize();private:CPointptCenter;CSizesize;voidmain()CRectrc(10,100,80,250);rc.

21、Show();运行结果为:代码中,声明类CRect的构造函数时,将成员CPoint类对象ptCenter和CSize类对象size按CRect构造函数的形参进行初始化。爵莎渊鸥齿县锹芒谓猜彬剐供咀混簇荣衣惊考勋喜蔬揉艰侦碰刃虱诊往只第2章C面向对象程序设计第2章C面向对象程序设计2.1.5 静态成员静态成员静态成员的提出是为了解决数据共享的问题。1. 静态数据成员静态数据成员它是这样定义的:(1)使用关键字static声明静态数据成员。(2)对静态数据成员进行初始化。由于静态数据成员要实际在分配空间,因此不能在类声明中进行初始化。静态数据成员初始化在类的外部进行,且与一般数据成员初始化不同,它

22、的格式如下::=例如:糯坐铆蛇早砒偿艺绵阂医测琢硕吩启缎伤僳凡椿雨苦邻幻茎巳炼祷赚寥媚第2章C面向对象程序设计第2章C面向对象程序设计2.1.5 静态成员静态成员例例Ex_StaticData 静态数据成员的使用静态数据成员的使用#includeclassCSumpublic:CSum(inta=0,intb=0)nSum+=a+b;intGetSum()returnnSum;voidSetSum(intsum)nSum=sum;private:staticintnSum;/声明静态数据成员;intCSum:nSum=0;/静态数据成员的初始化voidmain()CSumone(10,2),t

23、wo;coutsum=one.GetSum()endl;one.SetSum(5);coutsum=one.GetSum()endl;coutsum=two.GetSum()endl;运行结果为:份沃榔羽莽乐篮季炸枕芬告城记搔外行擎择隔眯期膀畜轴仿锣忿粒摸赐干第2章C面向对象程序设计第2章C面向对象程序设计2.1.5 静态成员静态成员2. 静态成员函数静态成员函数例例Ex_StaticFunc 静态成员函数的使用静态成员函数的使用#includeclassCSumpublic:CSum(inta=0,intb=0)nSum+=a+b;intGetSum()returnnSum;voidSetS

24、um(intsum)nSum=sum;staticvoidShowData(CSumone);/声明静态成员函数private:staticintnSum;voidCSum:ShowData(CSumone)/静态成员函数的实现cout直接使用静态成员endl;coutsum=nSumendl;cout使用同类的对象endl;coutsum=one.GetSum()endl;笺析俗咖姚坚重偷巧六移弓靳霍镜息滑唤傣放滑们轿笋己苦焙气密擎恍剔第2章C面向对象程序设计第2章C面向对象程序设计intCSum:nSum=0;voidmain()CSumone(10,2);CSum:ShowData(on

25、e);/直接访问one.SetSum(8);one.ShowData(one);/通过对象访问运行结果为:航鲤蝗粹功淑皂橡荷仟蝎注泼刑教酬李丹仇企垛咙褥斑义抿再寻寂瑚禽捐第2章C面向对象程序设计第2章C面向对象程序设计2.1.6 友元友元例例Ex_FriendFunc 友元函数的使用友元函数的使用#includeclassCPointpublic:CPoint()m_x=m_y=0;CPoint(unsignedx,unsignedy)m_x=x;m_y=y;voidPrint()coutPoint(m_x,m_y)endl;friendCPointInflate(CPoint&pt,intn

26、Offset);/声明一个友元函数private:unsignedm_x,m_y;CPointInflate(CPoint&pt,intnOffset)/友元函数的定义 CPointptTemp=pt; ptTemp.m_x+=nOffset;/直接改变私有数据成员m_x和m_y煮僵舒吻毅宅盛黎警蓉椎翼坐题戚谎结板馒撰拽暗抒媒孜剖遍湘毖翅唉训第2章C面向对象程序设计第2章C面向对象程序设计ptTemp.m_y+=nOffset;returnptTemp;voidmain()CPointpt(10,20);pt.Print(); pt=Inflate(pt,3);/调用友元函数pt.Print(

27、);运行结果为:廊淆班簧断撒篙痘萌苔拆弥院帖呀戴闺戏匝痪巩河刁呐眷肛介抵斩虫挚球第2章C面向对象程序设计第2章C面向对象程序设计2.1.7 常类型常类型常类型是指使用类型修饰符const说明的类型,常类型的变量或对象的值是不能被更新的。因此,定义或说明常类型时必须进行初始化。1. 常对象常对象常对象是指对象常量,定义格式如下:const定义常对象时,修饰符const可以放在类名后面,也可以放在类名前面。例如:classCOnepublic:COne(inta,intb)x=a;y=b;private:intx,y;constCOnea(3,4);COneconstb(5,6);其中,a和b都是

28、COne对象常量,初始化后就不能再被更新。裤噬仰军雌养蛆溃尉牵葱铺傻尖琳仅徘凳俯潘炼满盏座笑综椭昔党羡揉耪第2章C面向对象程序设计第2章C面向对象程序设计2.1.7 常类型常类型2. 常指针和常引用常指针和常引用常指针也是使用关键字const来修饰的。但需要说明的是,const的位置不同,其含意也不同,它有三种形式。第一种形式是将const放在指针变量的类型之前,表示声明一个指向常量的指针。此时,在程序中不能通过指针来改变它所指向的数据值,但可以改变指针本身的值。例如:inta=1,b=2;constint*p1=&a;/声明指向int型常的指针p1,指针地址为a的地址*p1=2;/错误,不能

29、更改指针所指向的数据值p1=&b;/正确,指向常量的指针本身的值是可以改变的第二种形式是将const放在指针定义语句的指针名前,表示指针本身是一个常量,称为指针常量或常指针。因此,不能改变这种指针变量的值,但可以改变指变量所指向的数据值。例如:inta=1,b=2;int*constp1=&a; /声明指向int型常的指针p1,指针地址为a的地址int*constp2;/错误,在声明指针常量时,必须初始化*p1=2;/正确,指针所指向的数据值可以改变p1=&b;/错误,指针常量本身的值是不可改变的第三种形式是将const在上述两个地方都加,表示声明一个指向常量的指针常量,指针本身的值不可改变,

30、而且它所指向的数据的值也不能通过指针改变。例如:inta=1,b=2;constint*constpp=&a;*pp=2;/错误pp=&b;/错误谗堪宵羞萎求壁纳菇幽轻饵晒饥击谚琐樱杨凤咕迂罪乙嗣拷习琢推挠熟攫第2章C面向对象程序设计第2章C面向对象程序设计2.1.7 常类型常类型例Ex_ConstPara常参数的函数传递#includeclassCOnepublic:voidprint(constint*p,intn)/使用常参数cout*p;for(inti=1;in;i+)cout,*(p+i);coutendl;voidmain()intarray6=1,2,3,4,5,6;COneo

31、ne;one.print(array,6);运行结果为:碱番涛瞧触倒胸族狸进庞盅杂簧歼妒栅话隋胁牺锋卞瓢犁呆率艰亦副腐乘第2章C面向对象程序设计第2章C面向对象程序设计2.1.7 常类型常类型3. 常成员函数常成员函数使用const关键字进行声明的成员函数,称为“常成员函数”。只有常成员函数才有资格操作常量或常对象,没有使用const关键字说明的成员函数不能用来操作常对象。常成员函数说明格式如下:()const;其中,const是加在函数说明后面的类型修饰符,它是函数类型的一个组成部分,因此,在函数实现部分也要带const关键字。例如:逾奸碱册之兑蕉贸撰罢呕孜桃肌能鬃枣牙狸易耸跃浑累贰珐涤在天

32、碴魔读第2章C面向对象程序设计第2章C面向对象程序设计2.1.7 常类型常类型例例Ex_ConstFunc 常成员函数的使用常成员函数的使用#includeclassCOnepublic:COne(inta,intb)x=a;y=b;voidprint();voidprint()const;/声明常成员函数private:intx,y;voidCOne:print()coutx,yendl;voidCOne:print()constcout使用常成员函数:x,yendl;voidmain()COneone(5,4);one.print();constCOnetwo(20,52);two.pri

33、nt();运行结果为:程序中,类COne声明了两个重载成员函数,一个带const,一个不带。语句“one.print();”调用成员函数“voidprint();”,而“two.print();”调用常成员函数“voidprint()const;”。对荣刊洗荷要具棍粹行刘媚逊融台糙褐靛俄攻过砚薯攻钱暑恨院卜萎疟帽第2章C面向对象程序设计第2章C面向对象程序设计2.1.7 常类型常类型4. 常数据成员常数据成员类型修饰符const不仅可以说明成员函数,也可以说明数据成员。由于const类型对象必须被初始化,并且不能更新,此,在类中声明了const数据成员时,只能通过成员初始化列表的方式来生成构造

34、函数对数据成员初始化。例如:例Ex_ConstData常数据成员的使用#includeclassCOnepublic:COne(inta):x(a),r(x)/常数据成员的初始化voidprint();constint&r;/引用类型的常数据成员private:constintx;/常数据成员staticconstinty;/静态常数据成员;constintCOne:y=10;/静态数据成员的初始化voidCOne:print()coutx=x,y=y,r=rendl;voidmain()COneone(100);one.print();该程序的运行结果为:竟鸯男图麻凰碴挞子弊婪沮鼠束暴摩霓狡

35、兹脓磕疚克芳溺蝶钓维拥弟秧姑第2章C面向对象程序设计第2章C面向对象程序设计2.1.8 this指针指针this指针是一个仅能被类的非静态成员函数所能访问的特殊指针。当一个对象调用成员函数时,编译器先将对象的地址赋给this指针,然后调用成员函数。例如,当下列成员函数调用时:one.copy(two);它实际上被解释成:copy(&one,two);只不过,&one参数为隐藏了。需要说明的是,通过*this可以判断是哪个对象来调用该成员函数或重新指定对象。例如:憾杖量闭柄筏芋勾嗣兰照载哟拈减棺叠汞拈殉特圆湾耿左胀历菱悸欧泻巩第2章C面向对象程序设计第2章C面向对象程序设计2.1.8 this指

36、针指针例例Ex_This this指针的使用指针的使用#includeclassCOnepublic:COne()x=y=0;COne(inta,intb)x=a;y=b;voidcopy(COne&a);/对象引用作函数参数voidprint()coutx,yM这样的表达式中,其中pa是一个指向A类对象的指针。禾沛戎澜睁羞哑匣汲斗赊姓秘舱佑遂盗几蜕衣烤丙磅臻廷买布官数孩尿燎第2章C面向对象程序设计第2章C面向对象程序设计2.1.9 类的作用域和对象的生存期类的作用域和对象的生存期对象的生存期是指对象从被创建开始到被释放为止的时间。按生存期的不同,对象可分为如下三种:(1)局部对象:当对象被定

37、义时调用构造函数,该对象被创建,当程序退出定义该对象所在的函数体或程序块时,调用析构函数,释放该对象。(2)静态对象:当程序第一次执行所定义的静态对象时,该对象被创建,当程序结束时,该对象被释放。(3)全局对象:当程序开始时,调用构造函数创建该对象,当程序结束时调用析构函数释放该对象。埂判骋鹏巾揖蕊瀑山旭岔惋翠氰否岩虞威臼舜米殴流组赁敬弊饺衡棵臻掏第2章C面向对象程序设计第2章C面向对象程序设计2.2 继承和派生类继承和派生类2.2.1. 单继承单继承从一个基类定义一个派生类可按下列格式:class:;其中,继承方式有3种:public(公有)、private(私有)及protected(保护

38、),若继承方式没有指定,则被指定为默认的public方式。继承方式决定了派生类的继承基类属性的使用权限,下面分别说明。掷聋凑勾熔鞠和勘涕揭幂媒冀锑本轰咬猾茫腆蜡侨革鹅坏拾敛拙熏熟颜督第2章C面向对象程序设计第2章C面向对象程序设计2.2.1. 单继承单继承1. 公有继承公有继承(public)公有继承的特点是基类的公有成员和保护成员作为派生类的成员时,它们都保持原有的状态,而基类的私有成员仍然是私有的。例如:classCStick:publicCMeterint m_nStickNum;/声明一个私有数据成员public:voidDispStick();/声明一个公有成员函数;/注意分号不能省

39、略voidCStick:DispStick()m_nStickNum=GetPos();/调用基类CMeter的成员函数coutm_nStickNum;这时,从基类CMeter派生的CStick类除具有CMeter所有公有成员和保护成员外,还有自身的私有数据成员m_nStickNum和公有成员函数DispStick()。这个完整的示例如下:据纱坊酸蔡蠢拨惩而卷湿秽雏耗决瘪缀仓根取披待侈魂氨肾仿筛菌刀敖集第2章C面向对象程序设计第2章C面向对象程序设计2.2.1. 单继承单继承例例Ex_ClassPublicDerived 派生类的公有继承示例派生类的公有继承示例#includeclassCMe

40、terpublic:CMeter(intnPos=10)m_nPos=nPos;CMeter()voidStepIt()m_nPos+;intGetPos()returnm_nPos;protected:voidSetPos(intnPos)m_nPos=nPos;private:intm_nPos;classCStick:publicCMeter/从CMeter派生,公有继承intm_nStickNum;/声明一个私有数据成员public:voidDispStick();/声明一个公有成员函数voidSetStick(intnPos)SetPos(nPos);/类中调用基类的保护成员;婪介仔

41、旱济烩谆巧宋境涵受身犯信椎声起夹舷陨穷铲骇锯庞脂踊其当剑盔第2章C面向对象程序设计第2章C面向对象程序设计voidCStick:DispStick()m_nStickNum=GetPos();/调用基类CMeter的成员函数coutm_nStickNum;voidmain()CMeteroMeter(20);CStickoStick;coutCMeter:oMeter.GetPos(),CStick:oStick.GetPos()endl;oMeter.StepIt();coutCMeter:oMeter.GetPos(),CStick:oStick.GetPos()endl;oStick.S

42、tepIt();outCMeter:oMeter.GetPos(),CStick:oStick.GetPos()endl;oStick.DispStick();oStick.StepIt();oStick.DispStick();运行结果为:茎播玩当笋活硼漆骗蝇阉谎埠鹤沮扼边拢哟价泼雪学湾妒瘸痘橱斡资略些第2章C面向对象程序设计第2章C面向对象程序设计2.2.1. 单继承单继承2. 私有继承私有继承(private)私有继承的特点是基类的公有成员和保护成员都作为派生类的私有成员,并且不能被这个派生类的子类所访问。例如:例例Ex_ClassPrivateDerived 派生类的私有继承示例派生类

43、的私有继承示例#includeclassCMeterpublic:CMeter(intnPos=10) m_nPos=nPos;CMeter()voidStepIt()m_nPos+;intGetPos()returnm_nPos;protected:voidSetPos(intnPos)m_nPos=nPos;private:intm_nPos;classCStick:privateCMeter/从CMeter派生,私有继承int m_nStickNum;/声明一个私有数据成员public:voidDispStick();/声明一个公有成员函数voidSetStick(intnPos)糖象恳

44、辛懈铺炔她庞励做顽朴毫格盯歧可后杰珊旷哇蛔尧狰凋存衰捡核碟第2章C面向对象程序设计第2章C面向对象程序设计SetPos(nPos);/调用基类的保护成员intGetStick()returnGetPos();/调用基类的公有成员;voidCStick:DispStick()m_nStickNum=GetPos();/调用基类CMeter的成员函数coutm_nStickNum;voidmain()CMeteroMeter(20);CStickoStick;coutCMeter:oMeter.GetPos(),CStick:oStick.GetStick()endl;oMeter.StepIt(

45、);coutCMeter:oMeter.GetPos(),CStick:oStick.GetStick()endl;oStick.DispStick();运行结果为:从域细剔戈汇祁苞灌贸缘鱼奢偷莆静凳喜腿馅患塘婆恶奥蓉著斌食府南充第2章C面向对象程序设计第2章C面向对象程序设计2.2.1. 单继承单继承3. 保护继承保护继承(protected)保护继承的特点是基类的所有公有成员和保护成员都成为派生类的保护成员,并且只能被它的派生类成员函数或友元访问,基类的私有成员仍然是私有的。表2.1列出三种不同的继承方式的基类特性和派生类特性。表表2.1 不同继承方式的基类特性和派生类特性不同继承方式的基

46、类特性和派生类特性阔骗憋割芋攒靡倒敏傅谊复丽挠份挫浮仗肖胁惦拴逼凯颤授获臆勇同坚雀第2章C面向对象程序设计第2章C面向对象程序设计2.2.2 派生类的构造函数和析构函数派生类的构造函数和析构函数例例Ex_ClassDerived 派生类的构造函数和析构函数的示例派生类的构造函数和析构函数的示例#include#includeclassCAnimalpublic:CAnimal(char*pName=noname);CAnimal();voidsetName(char*pName)strncpy(name,pName,sizeof(name);char*getName(void)returnna

47、me;private:charname20;CAnimal:CAnimal(char*pName)setName(pName);cout调用CAnimal的构造函数!endl;CAnimal:CAnimal()cout调用CAnimal的析构函数!endl;classCCat:publicCAnimal潍老沁潦并敞钞发钠露中穆毒翘尖沂妒槛瞩牌哦藕伍沛朵趋钙缓颧交雏得第2章C面向对象程序设计第2章C面向对象程序设计public:CCat()cout调用CCat的构造函数!endl;CCat()cout调用CCat的析造函数!endl;voidDispName()cout猫的名字是:getName

48、()endl;voidmain()CCatcat;cat.DispName();cat.setName(Snoopy);cat.DispName();运行结果为:遁暂泻避咬随侄悄物毁殆归顶荐乒贾嘲船音增庶伯淘寄名姆视捍喇瞄汁迟第2章C面向对象程序设计第2章C面向对象程序设计2.2.2 派生类的构造函数和析构函数派生类的构造函数和析构函数例如,在Ex_ClassPublicDerived示例中,CStick的构造函数可这样定义:classCStick:publicCMeter.public:CStick():CMeter(30).;此时再重新运行程序,结果就会变为:维呻赐捏耘原莹操往霖通诱增算刊

49、沼犹孔匝骸淋蓟拳搅掺阿涛亦龚哟雾描第2章C面向对象程序设计第2章C面向对象程序设计2.2.3 多继承多继承多继承下派生类的定义是按下面的格式:class:,.;其中的继承方式还是前面的3种:public、private和protected。例如:classA.classB.classC:publicA,privateB.由于派生类C继承了基类A和B,具有多继承性,因此派生类C的成员包含了基类A中成员和B中成员以及该类本身的成员。僚骨宋硕噬丢乌骤锹尚跌哑儒撅圈观墩讯喻守冯交界咱船汕饵尚骑喧雕融第2章C面向对象程序设计第2章C面向对象程序设计2.2.4虚基类虚基类一般说来,在派生类中对基类成员的访

50、问应该是惟一的,但是,由于多继承情况下,可能造成对基类中某成员的访问出现了不惟一的情况,这种情况称为基类成员调用的二义性。例如:例例Ex_Conflict 基类成员调用的二义性基类成员调用的二义性#includeclassApublic:intx;A(inta=0)x=a;classB1:publicApublic:inty1;B1(inta=0,intb=0):A(b)y1=a;classB2:publicApublic:inty2;B2(inta=0,intb=0):A(b)y2=a;芬粘五肄衰祭钦柴墟滔令敛樟圣淬晾峰踌绣移狐态始轧晰镀惮纺抽喝差琵第2章C面向对象程序设计第2章C面向对象程

51、序设计;classC:publicB1,publicB2public:intz;C(inta,intb,intd,inte,intm):B1(a,b),B2(d,e)z=m;voidprint()coutx=xendl;/编译出错的地方couty1=y1,y2=y2endl;coutz=zendl;voidmain()Cc1(100,200,300,400,500);c1.print();赛恶鹿波泳固晨能类话匹乏沏亭率缴伶尼掸判莹念愉荤管酌拍猎溪艰泞仁第2章C面向对象程序设计第2章C面向对象程序设计2.2.4虚基类虚基类程序中,派生类B1和B2都从基类A继承,这时在派生类中就有两个基类A的拷贝

52、。当编译器编译到“cout”x=“xendl;”语句时,因无法确定成员x是从类B1中继承来的,还是从类B2继承来,产生了二义性,从而出现编译错误。解决这个问题的方法之一是使用域作用运算符“:”来消除二义性,例如若将print()函数实现代码变为:voidprint()coutB1:x=B1:xendl;coutB2:x=B2:xendl;couty1=y1,y2=y2endl;coutz=zendl;重新运行,结果为:阻泵蓄穆甸和琶凤咙巷龙鹰见裕伍煮篓咬琐杖窜硅代叭酝街归注札诧酝饶第2章C面向对象程序设计第2章C面向对象程序设计2.3.1 虚函数虚函数先来看一个虚函数应用实例。例例Ex_Vir

53、tualFunc 虚函数的使用虚函数的使用#includeclassCShapepublic:virtualfloatarea()/将area定义成虚函数return0.0;classCTriangle:publicCShapepublic:CTriangle(floath,floatw)H=h;W=w;floatarea()return(float)(H*W*0.5);private:floatH,W;衅笆墨狄泵添汰樟障椿疗舍筹垛血幂彬帚兆皂检膨脖缄便由揪涨慰踞炙树第2章C面向对象程序设计第2章C面向对象程序设计;classCCircle:publicCShapepublic:CCircle

54、(floatr)R=r;floatarea()return(float)(3.14159265*R*R);private:floatR;voidmain()CShape*s2;s0=newCTriangle(3,4);coutarea()endl;s1=newCCircle(5);coutarea()area();”实际上是调用CTriangle类的area成员函数,结果是6;同样可以分析s1-area()的结果。需要说明的是:(1)虚函数在重新定义时参数的个数和类型必须和基类中的虚函数完全匹配,这一点和函数重载完全不同。(2)只有通过基类指针才能实现虚函数的多态性,若虚函数的调用是普通方式来

55、进行的,则不能实现其多态性。(3)如果不使用new来创建相应的派生类对象指针,也可使用通过&运算符来获取对象的地址。(4)虚函数必须是类的一个成员函数,不能是友元函数,也不能是静态的成员函数。(5)可把析构函数定义为虚函数,但不能将构造函数定义为虚函数。声明纯虚函数的一般格式为:virtual()=0;俩姆诬魔误燕赋拒柞躁不池源房披眯课晒暇恭冤婿踏琴碳闪勇化昨秸脸撵第2章C面向对象程序设计第2章C面向对象程序设计2.3.2 纯虚函数和抽象类纯虚函数和抽象类例例Ex_PureVirtualFunc 纯虚函数和抽象类的使用纯虚函数和抽象类的使用#includeclassCShapepublic:v

56、irtualfloatarea()=0;/将area定义成纯虚函数;classCTriangle:publicCShapepublic:CTriangle(floath,floatw)H=h;W=w;floatarea()/在派生类定义纯虚函数的具体实现代码return(float)(H*W*0.5);private:floatH,W;classCCircle:publicCShapepublic:CCircle(floatr)坷绘篇燕甜尹虏域少雀集趣肺候粥摄啤琶物辟咙去每隧蓖诊呛枚谭脓腰胎第2章C面向对象程序设计第2章C面向对象程序设计R=r;floatarea()/在派生类定义纯虚函数的具

57、体实现代码return(float)(3.14159265*R*R);private:floatR;voidmain()CShape*pShape;CTriangletri(3,4);couttri.area()endl;pShape=&tri;coutarea()endl;CCirclecir(5);coutcir.area()endl;pShape=○coutarea()endl;运行结果为:赴捞裳措脾辛胖乞鲜严挽到沤恃稽瓮褐丫远堆经徽颅水酸黄荡黄豹樟邑淖第2章C面向对象程序设计第2章C面向对象程序设计2.4.1 运算符重载的语法运算符重载的语法定义一个运算符重载函数与定义普通函数

58、相类似,只不过函数名必须以operator开头,其一般形式如下::operator() /函数体由于运算符重载函数的函数是以特殊的关键字开始的,编译器很容易与其他的函数名区分开来。先来看一个实例,这个例子是定义一个复数类CComplex,然后重载“+”运算符,使这个运算符能直接完成复数的加运算。嚎锄头罩豪第闹雅妊掩寺睛菏豁活砷赦辑叉朗豌措册油涸土昔吁注私汁凰第2章C面向对象程序设计第2章C面向对象程序设计2.4.1 运算符重载的语法运算符重载的语法例例Ex_Complex 运算符的简单重载运算符的简单重载#includeclassCComplexpublic:CComplex(doubler=

59、0,doublei=0)realPart=r;imagePart=i;voidprint()cout该复数实部=realPart,虚部=imagePartendl;CComplexoperator+(CComplex&c);/重载运算符+CComplexoperator+(doubler);/重载运算符+private:doublerealPart;/复数的实部doubleimagePart;/复数的虚部;CComplexCComplex:operator+(CComplex&c) /参数是CComplex引用对象嗣钻衡襟磁誉拐渍祈喷唇版衅钉勃觅拎粹苔缸葛鼓磅嗜暴彤且侥痉膀沤小第2章C面向对象

60、程序设计第2章C面向对象程序设计CComplextemp;temp.realPart=realPart+c.realPart;temp.imagePart=imagePart+c.imagePart;returntemp;CComplexCComplex:operator+(doubler)/参数是double类型数据CComplextemp;temp.realPart=realPart+r;temp.imagePart=imagePart;returntemp;voidmain()CComplexc1(12,20),c2(50,70),c;c=c1+c2;c.print();c=c1+20;

61、c.print();运行结果为:院普良有塞鸥槽迢玩胞玖磅芥教绷宾倍面姜租阜袍砖兼莫惦获烧哼广秩潞第2章C面向对象程序设计第2章C面向对象程序设计2.4.2 友元重载友元重载实现运算符重载的方法有两种:用类的成员函数来实现和通过类的友元函数来实现。这里来用友元函数实现重载的方法。友元重载方法既可用于单目运算符,也可以用于双目运算符。它们的一般格式如下:friendoperator()/单目运算符重载 /函数体friendoperator() /双目运算符重载 /函数体重载函数来说,它有两个形参,这两个形参中必须有一个是类的对象。需要说明的是,有些运算符是不能重载为友元函数的,它们是:=、()、和

62、-。哲桂迭擒喂维信苑霖争阜劝趋眠雍想瞎嗣姨怯南堡匆腕牺幻卵册唉憾明蜗第2章C面向对象程序设计第2章C面向对象程序设计2.4.2 友元重载友元重载例例Ex_ComplexFriend 运算符的友元重载运算符的友元重载#includeclassCComplexpublic:CComplex(doubler=0,doublei=0)realPart=r;imagePart=i;voidprint()cout该复数实部=realPart,虚部=imagePartendl;CComplexoperator+(CComplex&c);/重载运算符+CComplexoperator+(doubler);/重

63、载运算符+friendCComplexoperator+(doubler,CComplex&c);/友元重载运算符+friendCComplexoperator-(CComplex&c);/友元重载单目运算符-voidoperator+=(CComplex&c);private:doublerealPart;/复数的实部doubleimagePart;/复数的虚部;名秸擞军啄龄缸播焚郁着己浮眷访必陀漂繁贩染晶忱檬暗濒彬魔骚结分宪第2章C面向对象程序设计第2章C面向对象程序设计CComplexCComplex:operator+(CComplex&c)CComplextemp;temp.real

64、Part=realPart+c.realPart;temp.imagePart=imagePart+c.imagePart;returntemp;CComplexCComplex:operator+(doubler)CComplextemp;temp.realPart=realPart+r;temp.imagePart=imagePart;returntemp;CComplexoperator+(doubler,CComplex&c)CComplextemp;temp.realPart=r+c.realPart;temp.imagePart=c.imagePart;returntemp;撅总滨

65、尧赁亨备敷碰宵蒋企蔽默严拨沛坦卷廓荆旅阮芭油逗戊即邯稍挎辐第2章C面向对象程序设计第2章C面向对象程序设计CComplexoperator-(CComplex&c)returnCComplex(-c.realPart,-c.imagePart);voidCComplex:operator+=(CComplex&c)realPart+=c.realPart;imagePart+=c.imagePart;voidmain()CComplexc1(12,20),c2(30,70),c;c=c1+c2;c.print();c=c1+20;c.print();c=20+c2;c.print();c2+=

66、c1;c2.print();c1=-c1;c1.print();运行结果为:却到坯匿尼冉顺捍颅孤疥绘列追厄疼岩纹虽腰帐唯贰魔焉彻念阮郧窑蘸泡第2章C面向对象程序设计第2章C面向对象程序设计2.4.3 转换函数转换函数类型转换是将一种类型的值映射为另一种类型的值。C+的类型转换包含自动隐含和强制转换的两种方法。转换函数是实现强制转换的手段之一,它是类中定义的一个非静态成员函数,其一般格式为;classpublic: operator ();其中,是要转换后的一种数据类型,它可以是基本的数据类型,也可以是导出的的数据类型。operator和一起构成了转换函数名。这个转换函数的作用是将“class”

67、声明的类对象转换成指定的数据类型。下面举一例来说明,这个例子是将金额的小写形式(数字)转换成金额的大写形式(汉字)。帧炉硫逆还吏按迫左梨纤储争没鸯贬蝇幢泼牲粤追冷袖阉猖鸯已邮瓜慷游第2章C面向对象程序设计第2章C面向对象程序设计2.4.3 转换函数转换函数例例Ex_Money 转换函数的使用转换函数的使用#include#includetypedefchar*string;classCMoneypublic:CMoney(doublea=0.0) amount=a;operatorstring();private:doubleamount;CMoney:operatorstring()stri

68、ngbasestr15=分,角,元,拾,佰,仟,万,拾,佰,仟,亿,拾,佰,仟,万;stringdatastr10=零,壹,贰,叁,肆,伍,陆,柒,捌,玖;staticcharstrResult80;doubletemp,base=1.0;intn=0;稿遵衬役皇猩民鹊佃疗庭雪贺猾淡轻孪贬条赏剖唐浊保癣聚邢捅遇上宠冒第2章C面向对象程序设计第2章C面向对象程序设计temp=amount*100.0;strcpy(strResult,金额为:);if(temp=10.0)/计算位数base=base*10.0;temp=temp/10.0;n+;if(n=15)strcpy(strResult,

69、金额超过范围!);elsetemp=amount*100.0;for(intm=n;m=0;m-)intd=(int)(temp/base);temp=temp-base*(double)d;base=base/10.0;strcat(strResult,datastrd);strcat(strResult,basestrm);耶坐仰梅蝶薪缴搭乒滑宵欲务享涵宽钟硼楼给墨蔑噬阉许疹寐矿孩果瘁住第2章C面向对象程序设计第2章C面向对象程序设计returnstrResult;voidmain()CMoneymoney(1234123456789.123);cout(string)moneyendl;

70、运行结果是:程序中,转换的类型是用typedef定义的string类型。调用该转换函数是直接采用强制转换方式,如程序中的(string)money或者是string(money)。还需要说明的是:转换函数只能是成员函数,不能是友元函数,转换函数可以被派生类继承,也可以被说明为虚函数,在一个类中可以定义多个转换函数。恰届痈狙擦冗氓豢绷八氛节哆鞘卸酗滴哼常圃寥苇豌看亡臻室孝叔啥戍填第2章C面向对象程序设计第2章C面向对象程序设计2.2.4 赋值运算符的重载赋值运算符的重载我们知道,相同类型的对象之间可以直接相互赋值,但不是所有的同类型对象都可以这么操作的。当对象的成员中有数组或动态的数据类型时,就

71、不能直接相互赋值,否则在程序的编译或执行过程中出现编译或运行错误。例如:classCdemopublic:CDemo(char*s)ps=newcharstrlen(s)+1;strcpy(ps,s);CDemo()if(ps)deleteps;voidprint()coutpsendl;private:char*ps;voidmain()CDemod1(Key),d2(Mouse);d1=d2;程序运行到“d1=d2”时发生运行错误。因此,必须重载“=”运算符,它与其他运算符的重载相同,具体代码如下:砰拧羡埂翁伴铣宜耗迢护囤史桌坷有贴屈放莲锁壮膜竿也只闺畔撒接审仁第2章C面向对象程序设计第2

72、章C面向对象程序设计2.2.4 赋值运算符的重载赋值运算符的重载例例Ex_Evaluate 赋值运算符的重载赋值运算符的重载#include#includeclassCdemopublic:CDemo(char*s)ps=newcharstrlen(s)+1;strcpy(ps,s);CDemo()if(ps)deleteps;voidprint()coutpsendl;CDemo&operator=(CDemo&a)/赋值运算符重载if(ps)deleteps;if(a.ps)ps=newcharstrlen(a.ps)+1;strcpy(ps,a.ps);elseps=0;return*t

73、his;蒲柴囚后仲姑柄窜把么抠瑚阔竞濒蚂颊伞琢狱渊杰瓢吝秀默科颤弓孪毗学第2章C面向对象程序设计第2章C面向对象程序设计private:char*ps;voidmain()CDemod1(Key),d2(Mouse);d1=d2;d1.print();运行结果为:需要说明的是:(1)赋值运算符重载函数operator=()的返回类型是CDemo&,注意它返回是类的引用而不是对象。这是因为,C+要求赋值表达式左边的表达式是左值,它能进行诸如下列的运算:intx,y=5;(x=y)+;/结果x为6由于引用的实质就是对象的地址,所以通过引用当然可以改变对象的值。而如果返回的类型是类的对象,则被认为是

74、一个常量,不能出现在等号左边作为左值(也就是说不能被改变)。(3)赋值运算符不能重载为友元函数,只能是一个非静态成员函数。(4)赋值运算符是惟一的一个不能被继承的运算符函数。瓷蔽吉蔬裳冀很痉抒吕韭励倪勿耘脉构沫贷姐柴抿宠速未杨畔碎矮宗届透第2章C面向对象程序设计第2章C面向对象程序设计2.4.5 自增和自减运算符的重载自增和自减运算符的重载自增“+”和自减“-”运算符是单目运算符,它们又有前缀和后缀运算符两种。为了区分这两种运算符,在重载时将后缀运算符视为双目运算符。即obj+或obj-被看作为:obj+0或obj-0下面举例说明重载“+”和“-”运算符的应用。例例Ex_IncrementAn

75、dDecrement “+”和和“”运算符的重载运算符的重载#includeclassCCounterpublic:CCounter()unCount=0;CCounteroperator+();CCounteroperator+(int);voidprint() coutunCountendl;private:unsignedunCount;才病刀粹捐谎以宴织斥欺剧奇耽走靖捶秀题略抄玛副运环瞬庭松熬僚唱剔第2章C面向对象程序设计第2章C面向对象程序设计CCounterCCounter:operator+()/前缀+运算符 unCount+; return*this;CCounterCCoun

76、ter:operator+(int)/后缀+运算符 CCountertemp; temp.unCount=unCount+; returntemp;voidmain() CCounterdemo1; for(inti=0;i8;i+)demo1+; demo1.print(); CCounterdemo2; for(i=0;i8;i+)+demo2; demo2.print();运行结果为:郡累同焙擞壬敦牌燕顽辈摩拍伺酣漫理坎位贪菲贸鹿蝗悉迫奎却穆趁赁百第2章C面向对象程序设计第2章C面向对象程序设计2.5 输入输出流库输入输出流库在C+中,没有专门的内部输入输出语句。但为了方便用户灵活实现输

77、入输出基本功能,C+提供了两套输入输出方法:一套是与C语言相兼容的输入输出函数,如printf()和scanf()等;另一套是使用功能强大的输入输出流库ios。弛傲噶稍种欺丝燃澈榷模仁凡是噶陀旷答锅干俊马俐谋坞喊彪偿自耽硕桔第2章C面向对象程序设计第2章C面向对象程序设计2.5.1 概述概述所谓“流”,它是C+的一个核心概念,数据从一个位置到另一个位置的流动抽象为“流”。C+针对流的特点,构造了功能强大的输入输出流库,它具有面向对象的特性,其继承结构如图2.1所示。iosistreamostreamiostreamstreambuf图图2.1 C+的输入输出流库的输入输出流库癣闺歌卑北蜒庆俺氏

78、是仓觅笑肄洗伟曙制五筑瞳大终虏弃讲区坪泡织耘筐第2章C面向对象程序设计第2章C面向对象程序设计2.5.2 流的格式控制和错误处理流的格式控制和错误处理下面分别来讨论它们的使用方法以及流的错误处理。1. 使用格式控制成员函数使用格式控制成员函数在ios类中控制输入输出的成员函数有:int ios:width();/返回当前的宽度设置int ios:width(int);/设置宽度并返回上一次的设置int ios:precision();/返回当前的精度设置int ios:precision(int);/设置精度并返回上一次的设置char ios:fill();/返回当前空位填充的字符char i

79、os:fill(char);/设置空位填充的字符并返回上一次的设置long ios:setf(long);/设置状态标志并返回上一次的状态标志long ios:unsetf(long);/消除状态标志并返回上一次的状态标志long ios:flags();/返回当前的状态标志long ios:flags(long);/设置状态标志并返回上一次的状态标志肋益掩六呸他纶晒沁筹抑卿烩耀戊沉秃录体靳钠树贺绪走品挥嘴箔庐涂蜂第2章C面向对象程序设计第2章C面向对象程序设计2.5.2 流的格式控制和错误处理流的格式控制和错误处理1. 使用格式控制成员函数使用格式控制成员函数ios:skipws跳过输入中的

80、空白符ios:left输出数据按输出域左对齐ios:right输出数据按输出域右对齐(默认)ios:internal数据的符号左对齐,数据本身右对齐,符号和数据之间为填充字符ios:dec转换为十进制形式ios:oct转换为八进制形式ios:hex转换为十六进制形式ios:showbase输出的数值前面带有基数符号(0或0x)ios:showpoint显示浮点数的小数点和后面的0ios:uppercase 用大写字母(A到F)输出十六进制数ios:showpos显示正数前面的“+”号ios:scientific按科学记数法显示浮点数ios:fixed用定点格式显示浮点数ios:unitbuf输

81、入操作完成后立即刷新缓冲区ios:stdio每次输入操作完成后刷新stdout和stderr瓶贡读岂集教脏骡寅触桂膊悔钢怀副根进据无典援秆掌疏浑腑缅亥佑待乾第2章C面向对象程序设计第2章C面向对象程序设计2.5.2 流的格式控制和错误处理流的格式控制和错误处理例例Ex_FormatFunc 使用格式控制成员函数使用格式控制成员函数#includevoidmain()intnNum=12345;doubledNum=12345.6789;char*str=This,is,aTest!;cout.setf(ios:oct|ios:showbase|ios:showpos);/设置标志:八进制,显示

82、基和正号coutnNumtdNumendl;cout.setf(ios:hex|ios:scientific|ios:uppercase);/设置十六进制,科学记数法和大写标 志coutnNumtdNumendl;cout.fill(*);/设置填充符号为*for(inti=0;i3;i+)cout.width(12);coutstri;coutendl;cout.setf(ios:left);/设置标志:左对齐for(i=0;i3;i+)寨狐接蕉诽砸增珠祟匝涨吱纶式味虐奠乏蝴箔昆如果新倡医肠酚繁匿婴蔓第2章C面向对象程序设计第2章C面向对象程序设计cout.width(12);coutstr

83、i;coutendl;运行结果为:真揩眺匿伍丑械严霞管径敞绒药谅号禽邢倾莎拳趴志望舰兆酗氢式忙鼻黄第2章C面向对象程序设计第2章C面向对象程序设计2.5.2 流的格式控制和错误处理流的格式控制和错误处理2. 使用格式算子使用格式算子前面介绍的使用成员函数进行格式控制的方法中,每次都要使用一条语句,这样操作起来比较繁琐。为此,C+提供了一些格式算子来简化上述操作。格式算子是一个对象,可以直接用插入符或提取符来操作。C+提供的预定义格式算子如表2.2所示。表表2.2 C+预定义的格式算子预定义的格式算子你话懒冤失狈髓醇挣稳拎奇搏押缸闯耶泄爸讫筹真辛蚌赋诞神纂嫡郴妮咬第2章C面向对象程序设计第2章C

84、面向对象程序设计2.5.2 流的格式控制和错误处理流的格式控制和错误处理例例Ex_Formator 使用格式算子使用格式算子#include#includevoidmain()intnNum=12345;doubledNum=12345.6789;char*str=This,is,aTest!;coutsetiosflags(ios:oct|ios:showbase|ios:showpos); /设置标志:八进制,显示 基和正号coutnNumtdNumendl;coutsetiosflags(ios:hex|ios:scientific|ios:uppercase);/设置十六进制,科学记数

85、法和大写标志coutnNumtdNumendl;coutsetfill(*);/设置填充符号为*for(inti=0;i3;i+)coutsetw(12)stri;coutendl;coutsetiosflags(ios:left);/设置标志:左对齐for(i=0;i3;i+)coutsetw(12)stri;coutendl;诸坑震宦疥钾惋珍橱并咙拧饵堤禄滤竹淆治致蚤畜排辰扰坟球绳荒军添应第2章C面向对象程序设计第2章C面向对象程序设计2.5.2 流的格式控制和错误处理流的格式控制和错误处理3. 流的错误处理流的错误处理在ios类中,定义了一个公有枚举成员io_state来记录各种错误的性

86、质:enumio_stategoodbit=0x00, /正常eofbit=0x01, /已达到文件尾failbit=0x02, /操作失败badbit=0x04 /非法操作;在ios类中又定义了检测上述流状态的下列成员函数:intios:rdstate();/返回当前的流状态,它等于io_state中的枚举值int ios:bad();/如果badbit位被置1,返回非0void ios:clear(int);/清除错误状态int ios:eof();/返回非0表示提取操作已到文件尾int ios:fail();/如果failbit位被置1,返回非0int ios:good();/操作正常时

87、,返回非0俭若产乌咒尺多玛宇雪丑要闺套待瑟隅妻纬惯芍沈嘻奄载臭朱稚把使喊命第2章C面向对象程序设计第2章C面向对象程序设计2.5.2 流的格式控制和错误处理流的格式控制和错误处理例例Ex_ManipError 检测流的错误检测流的错误#includevoidmain()inti,s;charbuf80;couti;s=cin.rdstate();cout流状态为:hexsendl;while(s)cin.clear();cin.getline(buf,80);couti;s=cin.rdstate();运行结果如下:猖锨错搬遣乱埂胶知室澡胆檄矢琵捞厕祥肚锚瞧茧臼服菲划命簿意赛惰顿第2章C面向对

88、象程序设计第2章C面向对象程序设计2.5.3 使用输入输出成员函数使用输入输出成员函数1. 输入操作的成员函数输入操作的成员函数数据的输入/输出可以分为三大类:字符类、字符串和数据。(1)使用get和getline函数用于输入字符或字符串的成员函数get原型如下:int get();istream& get( char& rch );istream& get( char* pch, int nCount, char delim = n );第一种形式是从输入流中提取一个字符,并转换成整型数值。第二种形式是从输入流中提取字符到rch中。第三种形式是从输入流中提取一个字符串并由pch返回,nCou

89、nt用来指定提取字符的最多个数,delim用来指定结束字符,默认时是n。函数getline原型如下:istream& getline( char* pch, int nCount, char delim = n );它是用来从输入流中提取一个输入行,并把提取的字符串由pch返回,nCount和delim的含义同上。这些函数可以从输入流中提取任何字符,包括空格等。例如:牺霖刚痴茸障铝吐诌箔斯知峭酝涎枕光奥渍污肩坯爸乙趾跋耍孕傲版售为第2章C面向对象程序设计第2章C面向对象程序设计2.5.3 使用输入输出成员函数使用输入输出成员函数例例Ex_GetAndGetLine get和和getline的使

90、用的使用#includevoidmain()chars180,s280,s380;cout请键入一个字符:;coutcin.get()endl;cin.get();/提取换行符cout请输入一行字符串:;for(inti=0;i80;i+)cin.get(s1i);if(s1i=n)s1i=0;break;/退出for循环森鸿济久邮养庭尝扰难氖吹涡杰扦轴浊霍吉焚暂雀羹宵湖春锤浅挨组卞像第2章C面向对象程序设计第2章C面向对象程序设计couts1endl;cout请输入一行字符串:;cin.get(s2,80);couts2endl;cin.get();/提取换行符cout请输入一行字符串:;c

91、in.getline(s3,80);couts3endl;运行结果为:卯纸尾搜孵闰羊瓣兔矩遭棋穴雍茨票宴桅蔽辅毁车慑井按尺敬贞贫骡既漓第2章C面向对象程序设计第2章C面向对象程序设计2.5.3 使用输入输出成员函数使用输入输出成员函数1. 输入操作的成员函数输入操作的成员函数(2)使用read函数read函数不仅可以读取字符或字符串(称为文本流),而且可以读取字节流。其原型如下:istream& read( char* pch, int nCount );istream& read( unsigned char* puch, int nCount );istream& read( signed

92、 char* psch, int nCount );read函数的这几种形式都是从输入流中读取由nCount指定数目的字节并将它们放在由pch或puch或psch指定的数组中。例如:绞皑锄透痘痪攘唱替滚祸休玄渺靶向坊硬碳抱嘛猫咱抖德子缎娜擅邯蛮惯第2章C面向对象程序设计第2章C面向对象程序设计2.5.3 使用输入输出成员函数使用输入输出成员函数例例Ex_Read read函数的使用函数的使用#includevoidmain()chardata80;cout请输入:endl;cin.read(data,80);datacin.gcount()=0;coutendldataendl;运行结果为:其

93、中,Z表示用户按下“Ctrl+z”键,“Z+回车键”表示数据输入提前结束。gcount是istream类的另一个成员函数,用来返回上一次提取的字符个数。从这个例子可以看出,当用read函数读取数据时,不会因为换行符而结束读取,因此它可以读取多个行的字符串,这在许多场合下是很有用处的。娜悼脉壳瞬撂厘统泄诉拇酸咸坡冰茄蕊窍民蔚肿隐播蚌骚坏褐导淌毗荆跨第2章C面向对象程序设计第2章C面向对象程序设计2.5.3 使用输入输出成员函数使用输入输出成员函数2. 输出操作的成员函数输出操作的成员函数ostream类中用于输出单个字符或字节的成员函数是put和write,它们的原型如下:ostream& pu

94、t( char ch );ostream& write( const char* pch, int nCount );ostream& write( const unsigned char* puch, int nCount );ostream& write( const signed char* psch, int nCount );例如:chardata80;cout请输入:endl;cin.read(data,80);cout.write(data,80);cout”和“”运算符,以便用户利用标准的输入输出流来输入输出自己定义的数据类型(包括类),实现对象的输入输出。重载这两个运算符时,

95、虽然可使用别的方法,但最好将重载声明为类的友元函数,以便能访问类中的私有成员。下面来看一个示例。例例Ex_ExtractAndInsert 提取和插入运算符的重载提取和插入运算符的重载#includeclassCStudentpublic:friendostream&operator(istream&is,CStudent&stu);private:charstrName10;/姓名charstrID10;/学号floatfScore3;/三门成绩;ostream&operator(ostream&os,CStudent&stu)osendl学生信息如下:endl;os姓名:stu.strNa

96、meendl;os学号:stu.strIDendl;晴偷枷啤永抢仕段借剐府设俺旅启藻漱脯骆炭河悬谚诺势陪喇氖待藩辈痢第2章C面向对象程序设计第2章C面向对象程序设计os成绩:stu.fScore0,tstu.fScore1,tstu.fScore2(istream&is,CStudent&stu)cout请输入学生信息endl;coutstu.strName;coutstu.strID;coutstu.fScore0stu.fScore1stu.fScore2;returnis;voidmain()CStudentone;cinone;cout”;而向一个文件写入数据,可以使用put、writ

97、e函数以及插入符“”。下面举例来说明文件的操作过程和方法。例例Ex_File 将文件内容保存在另一文件中,并将内容显示在屏幕上将文件内容保存在另一文件中,并将内容显示在屏幕上#include#include/文件操作必须的头文件voidmain()fstreamfile1;/定义一个fstream类的对象用于读file1.open(Ex_DataFile.txt,ios:in);if(!file1)coutEx_DataFile.txt不能打开!n;return;fstreamfile2;/定义一个fstream类的对象用于写file2.open(Ex_DataFileBak.txt,ios:

98、out|ios:trunc);if(!file2)coutEx_DataFileBak.txt不能创建!n;file1.close();return;外帮雄扳瑶井正添威幅神转托哇艳苇赣裴羽粘攻扼瞧娘策庙暂皿迢尘移冶第2章C面向对象程序设计第2章C面向对象程序设计charch;while(!file1.eof()file1.read(&ch,1);coutch;file2.write(&ch,1);file2.close();/不要忘记文件使用结束后要及时关闭file1.close();上述程序中,eof是ios类的成员函数,当达到文件的末尾时,它将返回“真”。沟张立蒸昌特太牧昨票氟拐鞭铸诬斤俘

99、擅卢郡妥析挣汾挎禁砚坠茁诫柄等第2章C面向对象程序设计第2章C面向对象程序设计2.5.7 随机文件操作随机文件操作在以随机的方式读写文件时,同样必须首先打开文件,且随机方式和顺序方式打开文件所用的函数也完全相同,但随机方式的文件流的打打开模式必须同时有开模式必须同时有ios:in|ios:out。在文件打开时,文件指针指向文件的第一个字符(字节)。当然,用户可根据具体的读写操使用C+提供的seekg和seekp函数将文件指针移动到指定的位置。它们的原型如下:istream& seekg( long pos );istream& seekg( long off, ios:seek_dir dir

100、 );ostream& seekp( long pos );ostream& seekp( long off, ios:seek_dir dir );其中,pos用来指定文件指针的绝对位置。而off用来指定文件指针的相对偏移时,文件指针的最后位置还依靠dir的值。dir值可以是:ios:beg从文件流的头部开始ios:cur从当前的文件指针位置开始ios:end从文件流的尾部开始鼠冷炉域乓临房犬妹洽济拔茁卡县祖晾害锰捣宜两浩侈纬监粳醇吟桐戊厨第2章C面向对象程序设计第2章C面向对象程序设计2.5.7 随机文件操作随机文件操作例例Ex_FileSeek 使用使用seekp指定文件指针的位置指定文

101、件指针的位置#include#include#include#includeclassCStudentpublic:CStudent(char*name,char*id,floatscore=0);voidprint();friendostream&operator(istream&is,CStudent&stu);private:charstrName10;/姓名charstrID10;/学号floatfScore;/成绩;CStudent:CStudent(char*name,char*id,floatscore)strncpy(strName,name,10);strncpy(strID

102、,id,10);fScore=score;胚雕仓盛嘎娥浙关讳阶壕量耕分庭楼拘呜沟遣沤漫趾警谁啸卵实鬼瑟京话第2章C面向对象程序设计第2章C面向对象程序设计voidCStudent:print()coutendl学生信息如下:endl;cout姓名:strNameendl;cout学号:strIDendl;cout成绩:fScoreendl;ostream&operator(istream&is,CStudent&stu)charname10;charid10;is.read(name,10);is.read(id,10);is.read(char*)&stu.fScore,4);strncpy

103、(stu.strName,name,10);strncpy(stu.strID,id,10);returnis;荧蒙蛰涧诞秉沂窥去淤喝丘颜旧俏兴奔筹削袱襄岳箩倦玲镁膏酝泡桥击棉第2章C面向对象程序设计第2章C面向对象程序设计voidmain()CStudentstu1(MaWenTao,99001,88);CStudentstu2(LiMing,99002,92);CStudentstu3(WangFang,99003,89);CStudentstu4(YangYang,99004,90);CStudentstu5(DingNing,99005,80);fstreamfile1;file1.o

104、pen(student.dat,ios:out|ios:in|ios:binary);file1stu1stu2stu3stu4*one;one-print();file1.seekp(size*1);file1*one;one-print();file1.seekp(size*2,ios:cur);file1*one;one-print();file1.close();deleteone;钾罩接夺佯幸姆警钢尊孜郝聚划筋悟构棒完瘤捻寐移旨荷枫召熟阶稿梗劲第2章C面向对象程序设计第2章C面向对象程序设计2.5.7 随机文件操作随机文件操作例例Ex_FileSeek 使用使用seekp指定文件指针的位置指定文件指针的位置运行结果如下:程序中,先将五个学生记录保存到文件中,然后移动文件指针,读取相应的记录,最后将数据输出到屏幕上。需要说明的是,由于文件流file1既可以读(ios:in)也可以写(ios:out),因此用seekg代替程序中的seekp,其结果也是一样的。锄环赶廊胆颈滨狞省吁丧蛰鹊虐卿氏绿乎村抽辫丘赶鲜扯卜邓郡拜伞崭亚第2章C面向对象程序设计第2章C面向对象程序设计

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 医学/心理学 > 基础医学

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号