C++基础PPT课件.ppt_第1页
C++基础PPT课件.ppt_第2页
C++基础PPT课件.ppt_第3页
C++基础PPT课件.ppt_第4页
C++基础PPT课件.ppt_第5页
已阅读5页,还剩163页未读 继续免费阅读

下载本文档

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

文档简介

第13章C+基础,北京邮电大学出版社,内容提要,C+概述C+对C的扩充C+面向对象程序设计(*),13.1C+概述,(1)保留字(2)数据描述(3)C与C+亦有不同之处,C+是从C语言的基础上发展而来的C语言编写的程序可以在C+下使用C语言源程序文件的扩展名为.CC+源程序文件的扩展名一般为.cppC与C+的不兼容性之处:,(1)保留字,保留字是一种语言中具有特定含义与用途的标识符,在程序中不能作为用户自定义标识符,(2)数据描述,在C+中,结构、联合和枚举类型名可直接作类型名定义变量如:structSTUDENTcharname20;/*学生姓名*/charnum10;/*学生学号*/intscore;/*成绩*/;C+中类型变量定义形式:STUDENTlisi;C语言中该类型变量定义形式:structSTUDENTlisi;,C+中若全局变量在定义变量的模块之外使用,即其它模块要使用它,则必须先使用extern说明符对该变量进行声明。C语言中void类型的指针可以赋值给任何类型的指针,C+中不能。定义:inta,*p_int;C语言中:void*p_void=C+中:p_int=(int*)p_void;(使用强制类型转换),(3)C与C+在函数上的不同:,C+中函数必须先定义或声明函数原型才能调用。C+中函数若有参数,则在函数声明中必须列出参数。C+中在函数定义时,形式参数的类型应在参数表中声明。intSum(inta,intb)return(a+b);C语言中,未说明为void类型的函数可以不返回值;C+中,未说明为void类型的函数(构造函数除外)都必须有返回值。,13.2C+对C的扩充,C+的输入输出(*)C+的行注释(*)const常量定义与使用局部变量的定义与全局变量作用域运算符(*)变量的引用(*)函数重载带缺省参数的函数内联函数new和delete算符,13.2.1C+的输入输出,在头文件iostream.h中,C+提供了标准流:标准输入流cin,缺省设备为键盘。标准输出流cout,缺省设备为显示器。标准出错输出流cerr,立即输出,缺省设备为显示器。标准出错输出流cerr的缓冲形式clog,缓冲区满输出,缺省设备为显示器。标准流是不需要打开与关闭文件就可以使用的流式文件。,(1)用标准输出流cout进行输出,格式:cout输出项;“”叫插入运算符,将输出项插入到输出流中例如:cout“ThisisaC+Programn”;相当于语句:printf(“ThisisaC+Programn”);,cout允许使用多个插入运算符“”将多个输出项插入到输出流中。插入运算符的结合方向是自左向右。例如:inta=15,b=32;cout“a=”an“b=”bn;输出结果为:a=15b=32在iostream.h中,定义了一个与n相同的控制字符endl。cout“a=”aendl“b=”bendl;,cout通过控制符setw来设置。格式为:setw(n)表明要为后续的一个输出项预留n列。如输出项长度不够n,则数据右对齐;如超过n列,则按实际长度输出。例如:cout“a=”setw(4)a“b=”bendl“a+b=”a+bendl“x=”setw(3)x从输入流中提取数据。例如:inta;floatx;cinax;/相当于scanf(“%d%f”,连续输入多个变量值时,各值以空格或回车分隔。,例13.1流cin与cout的使用,#includevoidmain()intscore;charname20;coutname;/输入姓名cinscore;/输入成绩cout“Yournameis”nameendl;cout“Yourscoreis”scorey_or_n;if(y_or_n=N|y_or_n=n)break;cout“n学生人数为:”nendl“平均成绩为:sum/nendl;,(2)全局变量作用域运算符:例13.5变量作用域示例。includeinta=10;main()floata=3.14;printf(“a=%fn”,a);输出结果为:3.140000C语言规定:局部变量与全局变量同名时,在局部变量作用域内,全局变量被屏蔽。,#includeinta=10;voidmain()floata=3.14;cout“a=”:aendl;输出结果为a=10C+通过作用域运算符“:”来使用全局变量a,13.2.5变量的引用,(1)引用的概念引用是以别名的方式来使用另一变量或常量,其作用是为变量取一个别名。引用的声明格式:类型标识符b是a的引用,亦即b是a的别名,对b的任何操作就是对a的操作。a和b具有相同的存储单元,只是名称不同而已,b就是a本身。,在使用引用时,应注意以下几个方面:创建一个引用时必须将其初始化成对某一具体变量或常量的引用;程序中不能改变引用对象,即不能改变成对另一变量或常量的引用;必须确保引用是和一个合法的存储单元相连;对常量的别名引用必须是const类型的引用。,(2)引用作为函数参数,C语言中,函数的参数传递有两种:一是值传递,把变量名作为实参。二是指针传递。C+扩展函数参数传递的第三种方式。即用引用型变量作为函数参数。,值传递,#includevoidSwap(inta,intb)inttemp;temp=a;a=b;b=temp;couta=a,b=bendl;voidmain()inti=5,j=10;couti=i,j=jendl;Swap(i,j);couti=i,j=jendl;程序执行结果为:i=5,j=10a=10,b=5i=5,j=10,传递变量的指针,#includevoidSwap(int*p1,int*p2)inttemp;temp=*p1;*p1=*p2;*p2=temp;voidmain()inta=5,b=10;cout“a=”a“,”“b=”bendl;/输出a,b交换前的值Swap(/输出a,b交换后的值程序执行结果为:a=5,b=10a=10,b=5,采用引用作为函数参数,#includevoidSwap(int/输出调用swap()后i,j的值程序执行结果为:i=5,j=10a=10,b=5i=10,j=5,(3)引用作为函数的返回值,#includeint/调用后t的值程序执行结果为:9t=910t=10,13.2.6函数重载,函数重载是指允许同一作用域用同一函数名来定义不同的函数。重载函数的参数必须具备以下差别之一:(1)函数参数个数不同。(2)函数参数类型不完全相同。函数的参数表称为函数的特征表。注意:(1)仅返回类型不同的函数不能重载;(2)若函数参数除其中一个是另一个的类型的const或引用外均相同,则不能重载。,例如:求两数之和的函数intSum(intn,intm);正确的重载:floatSum(floatn,floatm);/参数类型不同,可以重载intSum(intn,intm,intp);/参数个数不同,可以重载错误的函数重载:floatSum(intn,intm);/仅返回类型不同,不能重载。intSum(constintn,intm);/参数是同类型的const,不能重载。intSum(int/参数是同类型的引用,不能重载。,例13.10利用重载函数求不同类型、不同个数的数的最小值。,#includeintMin(intx,inty)returnxz)temp=z;returntemp;floatMin(floatx,floaty,floatz)floattemp;if(xz)temp=z;returntemp;intmain()coutendlMin(5,10)endl;coutMin(10,4,8)endl;floatmin,x=10.1,y=15.1,z=8.4;min=Min(x,y,z);coutminmnq;max=Fmax(m,n,q);coutMax=maxendl;coutmn;max=Fmax(m,n);coutMax=maxx;cout“x的平方为:”Square(x)endl;cout“x+2的平方为:”Square(x+2)x;coutx的平方为:Square(x)endl;coutx+2的平方为:Square(x+2)id=”0309301”;PStudent-score=98;,例13.13new与delete使用示例,#include#includestructBookcharname20;floatprice;,voidmain()Book*b;b=newBook;strcpy(b-name,”C+Programming”);b-price=45.8;coutnamepricenameendl;不能再使用b程序执行结果:C+Programming45.8,13.3C+面向对象程序设计,类与对象(*)构造函数与析构函数(*)静态成员(*)友元(*)运算符重载继承与派生(*)多态性与虚函数(*)IO流文件输入输出流模板异常处理,13.3.1类与对象,面向对象程序设计方法就其实质而言是一种面向数据的程序设计方法,它谋求的是设计结果与问题在结构上保持一致。对象:将数据(或称为属性、状态)及施加在数据上的功能(或称为操作、行为、方法)捆绑在一起。类:由对象抽象而为类,通过继承形成类层次。对象间通过发送消息而相互联系和相互作用,从而完成系统的有关功能。,面向对象的程序设计语言应具有的特征:支持对象(Object)的有关概念;将对象抽象为类(Class);类通过继承(Inheritance)形成类层次;对象间通过传递消息(Message)而相互联系。,(1)对结构的扩充,C结构中只含有数据成员;C+的结构中增加了与数据成员的处理有关的函数,称之为成员函数。在C+中,结构体的成员通常分为两类:私有成员(private)公有成员(public)。在缺省的情况下,如例13.13,C+规定结构体的成员是公有的。,例13.14C+的结构体示例,#include#includestructCOMPLEXdoublereal;doubleimage;doubleAbsComplex()doubletemp;temp=real*real+image*image;returnsqrt(temp);;,intmain()COMPLEXcpl;cpl.real=6;cpl.image=8;cout“复数“cpl.real+cpl.imagei“的绝对值为:”;coutcpl.AbsComplex()endl;return0;程序执行结果为:复数6+8i的绝对值为:10,(2)类与对象,类:就是对一组具有相同属性(特征)和操作(行为)的事物的抽象描述。“类”由“对象”进行抽象而成一个“对象”就是一个“类”的具体实例举例:“学生”类,某个学生“刘伟”就是一个对象。对象具有以下几个方面的特征:对象的标志符或名字;描述对象的属性;与对象的属性有关的操作。,例如:“刘伟”是一个“学生”对象。,对象名:刘伟对象的属性:姓名:刘伟学号:00001年龄:22性别:男总分:712对象的操作:修改,类声明形式,class类名private:私有数据成员和成员函数public:公有数据成员和成员函数protected:保护数据成员和成员函数;,说明:,类声明中的private、public和protected三个关键字的出现次序和次数可以是任意的。如果private在类声明一开始就出现,则可以省略。private、public和protected用来设置访问安全保护措施:private后声明的数据成员和成员函数只能被类的成员函数和友元函数访问;public后声明的数据成员和成员函数没有访问限制;protected同private基本相似,不同:子类可以使用protected之后声明的数据成员和成员函数,但不能使用private之后声明的数据成员和成员函数。数据成员的数据类型可以是任何数据类型,但不能用auto、register或extern修饰,且不能在类声明时赋初值。,例如:学生类的定义,classCstudentprivate:/私有成员charName20;intId;intScore;public:/公用成员voiddisplay()/类的成员函数,是类的实现coutNameendl;coutIdendl;coutScoreendl;/类定义结束,其后的分号不能少Cstudentst1,st2;/创建Cstudent类的两个对象st1、st2,类中的常见成员函数(7类),构造函数:用来对数据成员进行初始化,创建对象时调用,名字与类名相同,一个类可有多个构造函数,但参数个数或类型应不同。析构函数:用来释放分配给对象的空间,撤销对象时调用,名字是在构造函数名前加一个波浪号(),且函数没有参数,无返回值,一个类只有一个。静态成员函数:成员函数之前有“static”关键字,一般用于静态数据成员或全局变量的访问,同静态数据成员一样,为该类的所有对象共享。内联成员函数:一般在类内部定义,调用该成员函数时,C+编译器将用函数体中的代码替代函数调用表达式。虚函数:成员函数前有“Virtual”关键字。const成员函数:const对象是一个常量,非const成员函数有可能修改数据成员,const成员函数是用来为const对象服务的。友元函数:声明时函数前加“friend”关键字。它可以是另一个类的成员函数,也可以是不属于任何类的普通函数。,例13.15类的使用示例,#include#includeclassCstudent/类定义开始private:intId;/学号floatScore;/成绩public:charName20;voidSetScore(floatBlscore)Score=Blscore;floatDisScore()returnScore;voidSetId(intIdnum);/置学号成员函数声明,intDisId();/声明显示学号函数/声明显示类的各成员变量的成员函数voidDisplay()coutNameendl;coutIdendl;coutScoreendl;/类定义结束,其后的分号不能少/在类的外部实现定义学号成员函数intCstudent:DisId()returnId;voidCstudent:SetId(intIdnum)Id=Idnum;,主函数中使用类:,程序执行结果为:姓名:刘伟学号:3301成绩:98刘伟330198,intmain()CstudentLiuwei;/创建一个Cstudent类对象Liuweistrcpy(Liuwei.Name,“刘伟”);/Name是类的公用数据成员,可以在类外使用。Liuwei.SetId(3301);/学号与成绩是私有成员,只能由成员函数使用/不能Liuwei.Id=3301;Liuwei.SetScore(98);cout姓名:Liuwei.Nameendl;cout学号:Liuwei.DisId()endl;cout成绩:Liuwei.DisScore()endl;Liuwei.Display();return0;,外部定义成员函数的一般格式为:,函数类型类名:函数名(形参说明表列)函数体例如:上例中的设置学号成员函数。voidCstudent:SetId(intIdnum)Id=Idnum;注意:Cstudent:SetId(intIdnum)是一个整体,说明SetId()是类Cstudent中的成员函数。,消息(Message):,消息是“对象”与“对象”之间的联系接口,用于调用某个对象的成员函数(或称激活某个方法)一个消息由三个部分组成:消息的接受对象,即“类”的对象名;消息名,即类中公有成员函数的函数名;零个或多个参数,即公有成员函数的形式参数。例如:向“STUDENT”类的一个对象“Liuwei”发送一个消息,通知它执行“Display”方法,消息表示为:Liuwei.Display();“Liuwei”为消息接受的对象“Display”为消息名消息不带参数,对象由相应的方法对消息进行响应。,13.3.2构造函数与析构函数,(1)构造函数构造函数:与类同名的特殊成员函数,声明类对象时,构造函数被自动调用,为对象分配内存空间,对该对象进行初始化。构造函数的声明格式:class类名public:类名();/缺省构造函数原型类名(参数表);/一般构造函数原型类名(类名intId;intScore;public:Cstudent()/类的缺省构造函数strcpy(Name,”刘伟”);Id=3301;Score=98;voidDisplay()coutNameendl;coutIdendl;coutScoreendl;,intmain()CstudentLiuwei;/系统自动调用构造函数Cstudent()对对象/Liuwei进行初始化/以下的初始化语句不需要了。/strcpy(Liuwei.Name,“刘伟”);/Liuwei.SetId(3301);/Liuwei.SetScore(98);cout姓名:Liuwei.Nameendl;cout学号:Liuwei.DisId()endl;cout“成绩:Liuwei.DisScore()endl;Liuwei.Display();return0;,带参数的构造函数:一般构造函数,#include#includeclassCstudentprivate:charName20;intId;intScore;public:Cstudent(charn20,inti,intsc=0);/构造函数原型声明,有形参,可缺省参数voidDisplay()cout姓名:Nameendl;cout学号:Idendl;cout成绩:Scoreendl;Cstudent:Cstudent(charn20,inti,intsc=0)strcpy(Name,n);Id=i;Score=sc;,intmain()CstudentLiuwei(“刘伟”,3301,98),WangWu(“王五”,3302);/创建两个Cstudent类对象Liuwei与/WangWu,以不同的实参进行初始化Liuwei.Display();WangWu.Display();return0;执行结果为:姓名:刘伟学号:3301成绩:98姓名:王五学号:3302成绩:0带形参的构造函数根据参数的不同完成不同的初始化。,拷贝构造函数,当构造函数将自己所在的类的引用作为参数时,称之为拷贝构造函数。拷贝构造函数的定义如下:C:C(constCintId;intScore;public:/一般构造函数,有形参,可缺省参数Cstudent(charn20,inti,intsc=0)strcpy(Name,n);Id=i;Score=sc;/拷贝构造函数,其参数为“引用”常量对象Cstudent(constCstudent,voidDisplay()cout“姓名:”Name“学号:”Id“”“成绩:”Scoreendl;intmain()CstudentLiuWei(“刘伟”,3301,98);/用普通构造函数创建LiuWeiCstudentWangWu(LiuWei);/用拷贝构造函数创建对象WangWu/用对象LiuWei的值对WangWu初始化LiuWei.Display();WangWu.Display();return0;程序执行结果:姓名:刘伟学号:3301成绩:98姓名:刘伟学号:3301成绩:98,对没有定义构造函数的类,若类的全部数据成员均为公有数据成员,则其对象的数据成员可以象结构体变量一样来初始化。,#include#includeclassCstudentpublic:charName20;intId;intScore;voidDisplay()cout“姓名:”Nameendl;cout“学号:”Idendl;cout“成绩:”ScoreXi=I;/显式的使用this指针;,(2)析构函数,构造函数:创建对象时自动完成为其分配内存空间及初始化工作,在对象使用完之后撤消对象的工作由类中另一个特殊函数,即析构函数来完成。析构函数的名字是在类名前加一个“”,以区别于构造函数。一个类只能有一个析构函数,析构函数不能被重载(构造函数可以重载)。不能带任何参数,也不能有返回值(包括void类型)。析构函数不能释放new申请的空间。对于用new动态申请的内存空间,则必须用delete操作释放。可以将delete放在析构函数中,在撤消对象时亦可释放new申请的空间。如果一个类没有显式地说明析构函数,则系统自动生成一个缺省的析构函数。,例13.18构造函数与析构函数使用示例,#include#includeclassCOMPLEXprivate:doublereal;doubleimage;public:doubleAbsComplex()doubletemp;temp=real*real+image*image;returnsqrt(temp);COMPLEX(doubler,doublei)real=r;image=i;COMPLEX()/析构函数cout自动调用析构函数endl;,intmain()COMPLEXcpl(6,8);/调用“构造函数”初始化对象的/私有成员real和image/COMPLEXc;/错误:因为“构造函数”有两个参数cout“复数6+8i的绝对值:”cpl.AbsComplex()endl;return0;,例13.19用户自定义析构函数,#include#includeclassCstudentprivate:char*Name;intId;intScore;public:Cstudent(char*n,inti,intsc=0)cout自动调用构造函数endl;Name=newchar20;/分配空间strcpy(Name,n);Id=i;Score=sc;,Cstudent()/析构函数if(Name)deleteName;/若Name非空,释放其占用的空间Name=NULL;voidDisplay()cout“姓名:”Name“”“学号:”Id“”“成绩:”Scoreendl;intmain()CstudentLiuWei(“刘伟”,3301,98);/用构造函数创建对象LiuWeiLiuWei.Display();return0;,13.3.3静态成员,关键字static用于一个类的成员,声明它们为静态的,称这样的成员为静态成员。一旦把类的成员函数声明为静态,将为所有该类的对象所共享。任意一个对象对静态成员的操作结果都会影响该类的其它对象。使用静态数据成员的主要目的是为了实现一个类的不同对象之间共享数据。类的静态成员分为静态数据成员与静态成员函数。,(1)静态数据成员,格式static数据类型数据成员变量名;注意:静态数据成员不能在构造函数中进行初始化,必须使用之前放在类外进行,也不需要加static。静态数据成员初始化格式:数据类型类名:静态数据成员名=初始值;,例13.20编程实现统计创建对象的个数,#includeclassObjCountprivate:staticintcount;/静态数据成员声明public:staticinttest;/静态数据成员声明ObjCount()count+;/构造函数intGetValue()returncount;/静态数据成员初始化,须在类外进行intObjCount:count=0;intObjCount:test=0;,voidmain()ObjCountobj1,obj2,obj3,obj4;cout“Thenumberofobjectsfromobj1is”obj1.GetValue()endl;cout“Thenumberofobjectsfromobj3is”obj3.GetValue()endl;cout“Thenumberofobjectsfromobj4is”obj4.GetValue()endl;cout+(ObjCount:test)endl;/不通过成员函数来访问公有静态成员。输出结果为:Thenumberofobjectsfromobj1is4Thenumberofobjectsfromobj3is4Thenumberofobjectsfromobj4is41,(2)静态成员函数,格式:static成员函数声明;调用:可以通过对象来调用,也可以不通过对象而直接调用。直接调用:必须指明其所属的类,以确定是调用静态成员函数。静态成员函数只能与类联系,不属于任何对象,例:编程实现统计创建对象的个数,#includeclassObjCountprivate:staticintcount;/静态数据成员声明public:ObjCount()count+;/构造函数staticintGetValue()/静态成员函数声明returncount;/静态数据成员初始化,须在类外进行intObjCount:count=0;,voidmain()cout“Thenumberofobjectsfromthestaticnumberfunctionis”ObjCount:GetValue()endl;/对象未创建,直接调用ObjCountobj1,obj2,obj3,obj4;cout“Thenumberofobjectsfromobj1is“obj1.GetValue()endl;coutThenumberofobjectsfromthestaticnumberfunctionis“ObjCount:GetValue()endl;,输出结果为:Thenumberofobjectsfromthestaticnumberfunctionis0Thenumberofobjectsfromobj1is4Thenumberofobjectsfromthestaticnumberfunctionis4,13.3.4友元,声明:友元可以在类的私有部分或公有部分声明,方法:在友元名称前加关键字friend。注意:友元本身虽然在类中声明,但它不是类的成员。,(1)友元函数,友元函数的声明格式:friend函数类型函数名(参数表);声明位置:可以在类的私有部分或公有部分中声明。具体实现:可在类的内部完成定义,也可以在类外定义。注意:类外定义友元函数,与普通函数的定义方法相同,但在它前面不能加friend与类名。构造函数、析构函数与虚拟函数声明为友元函数。,例13.21友元函数的使用,#include#includeclassCstudentprivate:intId;/学号floatScore;/成绩charName20;public:/公用成员Cstudent();/声明缺省构造函数voidDisplay();friendvoidDisplayFriend(Cstudentst);/友员函数声明;Cstudent:Cstudent()strcpy(Name,“刘伟”);Id=3301;Score=98;voidCstudent:Display()cout“成员函数显示:endl;cout“姓名:Name学号:Id“成绩:Scoreendl;,/友元函数定义voidDisplayFriend(Cstudentst)cout“友元函数显示:endl;cout姓名:st.Nameendl;cout学号:st.Idendl;cout成绩:st.Scoreendl;intmain()CstudentLiuwei;Liuwei.Display();DisplayFriend(Liuwei);/调用友元函数显示return0;程序执行结果为:成员函数显示:姓名:刘伟学号:3301成绩:98友元函数显示:姓名:刘伟学号:3301成绩:98,注意:,友元函数虽然可以直接访问类中的所有成员,但不是成员函数友元函数没有this指针,不能通过this来访问数据成员,必须通过参数传递来的对象名或对象指针来使用该对象的成员例如:例中的DisplayFriend()函数。在调用友元函数DisplayFriend()显示时,将对象Liuwei作为实参传入友元函数:DisplayFriend(Liuwei)。,(2)友元类,如果一个类要访问另一个类的私有成员时,可以将该类声明为另一类的友元。如将B类声明为A类的友元,在A类定义中加入友元声明语句:friendclassB;一旦类B声明为类A的友元类,B类的所以成员函数都可视为A类的友元函数,能存取A类的私有成员与保护成员。,例如:,classAintdata;friendclassB;/在A类中声明B是A的友元类public:voidset(int);,classBpublic:voidf1(A,13.3.5运算符重载,C+中有两种重载:函数重载函数重载是指同一作用域内的若干参数特征不同的函数可以使用相同的函数名字。运算符重载运算符重载则是指赋予运算符多重定义,使同一运算符可以施加于不同类型的操作数上。,运算符重载的一般格式为:返回类型operator运算符(参数表)/为运算符定义的操作代码operator是关键字。进行运算符重载时,函数参数个数的处理方法:1)对非成员函数,若运算符是单目的,则有一个参数;若为双目的,则有两个参数;2)对成员函数,若运算符是单目的,则无参数;若为双目的,则有一个参数。,例13.22运算符重载示例,#includeclassCOMPLEX/“复数”类floatreal;floatimage;public:COMPLEX(floatr=0.0,floatimage=0.0);voidDisplay();COMPLEXoperator+(COMPLEXcomp);/复数加,双目COMPLEX,voidCOMPLEX:Display()if(image0)coutrealimageiendl;elsecoutreal+imageiendl;COMPLEXCOMPLEX:operator+(COMPLEXcomp)/双目运算符重载,一个形参COMPLEXtemp;temp.real=real+comp.real;temp.image=image+comp.image;returntemp;COMPLEX,COMPLEXCOMPLEX:operator+()+real;+image;return*this;COMPLEXCOMPLEX:operator+(int)/形参在这里不参与运算,只作函数重载特征COMPLEXtemp;/创建一个对象temp.real=real+;temp.image=image+;returntemp;COMPLEXoperator-(COMPLEX,voidmain()COMPLEXcompx(5,6),compy(7,8),compz;coutcompx=;compx.Display();coutcompy=;compy.Display();compz=compx+compy;coutcompz=compx+compy=;compz.Display();compz=-compx;cout“compz=-compx后compz的值为:”;compz.Display();/负数-compx;cout“-compx的值为:”;compx.Display();/自减,前缀方式compz=+compx;cout“+compx的值为:”;compz.Display();/自增,前缀方式compz=compx+;cout“compx+的值为:”;compz.Display();/compz的值应为cx未自增前的值cout等重载为成员函数;其它二元运算符重载为非成员函数。,13.3.6继承与派生(*),继承(Inheritance):利用已有的数据类型定义出新的数据类型。基类(baseclass):也称父类,指已有类(被继承)基类是若干“类”的共性进一步抽象后形成的更抽象的类。派生类(derivedclass):也称子类,指新生成的类派生类继承了基类的所有数据成员与成员函数,不必重复定义基类中已有的相同成员。继承的作用:通过继承,类与类之间形成一个层次结构:。上层为基类(父类)。下层为派生类(子类)单重继承:如果一个派生类只有一个基类,则称单重继承。多重继承:如果一个派生类有若干个基类,则称多重继承。,示例,(1)派生类声明,单一继承,声明派生类格式class派生类名:派生方式基类名/派生类新增的数据成员/派生类新增的成员函数;派生方式:引用权限,它反映了基类成员在派生类中的访问权限,有三种方式:Private,为缺省的派生方式PublicProtected,表13.1基类成员在派生类中的访问权限,多重继承,声明派生类格式class派生类名:派生方式1基类1,派生方式2基类2,/派生类新增的数据成员/派生类新增的成员函数;例如classZ:W,publicX,protectedY/派生类Z新增的数据成员和成员函数;说明:/类Z私有继承了类W,公有继承了类X,保护继承了类Y,(1)派生类声明,(2)派生类的构造函数,派生类在继承基类的成员时,唯一不能继承的是基类中的构造函数和析构函数。当基类含有带参数的构造函数时,派生类必须定义构造函数,以提供将参数传递给基类的构造函数的途径。派生类构造函数的一般格式派生类构造函数名(参数表):基类构造函数表/基类构造函数表:由一至多个基类构造函数声明组成,以逗号分隔一般形式:基类构造函数名(参数表),例如:Z(intm,intn,intp):W(m),X(n),Y(p)/注意:如果派生类中含有对象成员时,对象成员的初始化形式与基类的初始化形式相似,只是将“基类构造函数名”改为“对象成员名”。Z(intm,intn,intp,intq):W(m),X(n),Y(p),member(q)/,(2)派生类的构造函数,说明:,定义派生类对象时,构造函数的执行顺序:基类的构造函数(派生类声明时从左到右的顺序)对象成员的构造函数(由对象成员在类中声明的先后次序决定)派生类的构造函数如果基类构造函数不带参数,则派生类不一定要定义构造函数。每个派生类只需对其直接基类的构造函数传递参数。如果在派生类中存在与基类同名的成员,使用派生类中定义的成员,则直接用该成员的名字。如果要用基类中声明的同名成员,则要用作用域运算符(:)来限定。如果想终止某一基类再被继承,可以使用私有派生方式加以限制;反之,则应采用公有派生方式。,例13.23派生类对基类的访问,#include#includeclassSTUDENT/学生类,基类private:structBIRTHDAYunsignedyear;unsignedmonth;birth;public:charname16;charid8;/学号STUDENT(unsignedy,unsignedm)/构造函数birth.year=y;birth.month=m;voidPrintBirth(void)/输出出生年月cout“出生年月:”birth.year“年”birth.month“月”endl;,classC_STUDENT:STUDENT/大学生派生类,继承STUDENT的内容charmajor20;/专业,STUDENT类原来没有的,新增的数据成员public:C_STUDENT(unsignedy,unsignedm,constchar*n,constchar*i,constchar*mj):STUDENT(y,m)/C_STUDENT的构造函数,使用了STUDENT的构造函数strcpy(name,n);/使用STUDENT中的公有数据成员namestrcpy(id,i);strcpy(major,mj);voidPrintInformation(void)/输出大学生信息cout“姓名:”nameendl;/使用STUDENT的公有数据成员namecout学号:idendl;cout专业:majorendl;/cout出生年月birth.year;/birth.year是STUDENT的私有数据成员,这里不能使用STUDENT:PrintBirth();/调用STUDENT的成员函数PrintBirth;,例13.23派生类对基类的访问(续),intmain()C_STUDENTst_obj(1983,10,刘伟,3301,信息工程);st_obj.PrintInformation();return0;程序执行结果为:姓名:刘伟学号:3301专业:信息工程出生年月:1983年10月,例13.23派生类对基类的访问(续),13.3.7多态性与虚函数(*),多态性(Polymorphism)是面向对象程序设计的第三个重要机制。多态性:同样的消息被不同类的对象接收导致完全不同行为的状态。同一个消息作用于不同的对象,其结果各不相同,具有多种形态。函数重载实现了一种多态性。,(1)静态联编与动态联编,联编(binding):将函数调用与相应函数体代码彼此相关联的过程。静态联编(staticbingding):联编在编译阶段完成,如重载函数。例如:求不同类型的两数中较小数的重载函数:intMin(inta,intb);floatMin(floatx,floaty);由于参数类型不同,编译程序据此自动选择对应的函数体进行匹配,即重载函数在编译时确定调用哪个函数。动态联编(dynamicbinding):在程序运行时进行联编,一般通过函数指针或引用来实现。,(2)虚函数,继承环境中,多态性通过虚函数(Virtualfunction)来实现。基类中定义虚函数,派生类可以重写基类中成员函数的代码,使类层次结构中同一个成员函数有不同本。虚函数:采用动态联编的方式实现。当一个基类类型指针指向派生类对象时,若向指针所指的对象发消息,则应该是派生类对象对应的函数代码被执行。但指针所指的对象可能只有在执行时才能知道到底执行哪些代码。,例13.24静态联编示例,#includeclassBASEintbx;public:BASE(intb)bx=b;/基类构造函数voidDisplay(void)cout“nBASE:”bx;/非虚函数voidInc(void)bx+;/非虚函数;classINHERITED:publicBASEintdx;public:INHERITED(intb,intd):BASE(b),dx(d)/派生类构造函数voidDisplay(void)coutnINHERITED:dx;voidInc(void)dx+;,voidfunc(BASE,coutendl对象引用;baseobj.Display();iobj.Display();coutendlDisplay()调用的都是基类成员函数Display()。若要调用派生类中的成员函数Display()必须通过对象来调用,或定义派生类指针实现。这种通过用户自己指定调用成员函数,在编译时根据类对象来确定调用该类成员函数的方式,是静态联编。给func()函数传递的对象,执行的结果都为BASE:6,而不是BASE:6与INHERITED:16。结果不是期望的。采用动态联编方式可解决这一问题。,例13.25虚函数实现多态性示例,#includeclassBASEintbx;public:BASE(intb)bx=b;/基类构造函数virtualvoidDisplay(void)coutnBASE:bx;/声明为虚函数virtualvoidInc(void)bx+;/声明为虚函数;classINHERITED:publicBASEintdx;public:INHERITED(intb,intd):BASE(b),dx(d)/派生类构造函数voidDisplay(void)coutnINHERITED:dx;voidInc(void)dx+;,voidfunc(BASE,baseobj.Display();iobj.Display();coutendl函数调用;func(baseobj)

温馨提示

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

评论

0/150

提交评论