【文档说明】第1章-C++面向对象程序的设计要点-课件.ppt,共(67)页,177.024 KB,由小橙橙上传
转载请保留链接:https://www.ichengzhen.cn/view-44716.html
以下为本文档部分文字说明:
第1章C++面向对象程序设计要点第1章C++面向对象程序设计要点1.1函数和函数参数1.2输入输出1.3类1.4抽象类型和模板第1章C++面向对象程序设计要点1.1函数和函数参数1.1.1函数类型C++中有两种类型函数:常规函数和成员函数。常规函数用于完成一个特定的功能,成员函数用于类方法
的定义。无论是常规函数还是成员函数,其定义都包括四个部分:函数名、形式参数表、返回类型和函数体。第1章C++面向对象程序设计要点函数的使用者通过函数名来调用函数,调用过程是把实际参数表传送给形式参数表作为函数的
数据来源,然后执行函数体中的语句实现该函数的功能,最后得到的返回值由函数名带回函数的调用者。成员函数是用于类方法定义的,因此,只有该类的对象才能调用其成员函数。第1章C++面向对象程序设计要点1.1.2函数名重载C++允许函数名
重载,即允许若干个相同的函数名能在相同作用域内使用。编译系统根据函数引用的参数类型和参数个数判明函数的使用。例1―1函数名重载#include<stdio.h>intmax(inta,intb){if(a>=b)returna
;elsereturnb;}第1章C++面向对象程序设计要点Floatmax(floata,floatb,floatc){if(a>=b&&a>=c)returna;elseif(a<b&&b>c)returnb;elseret
urnc;}voidmain(){printf("max(2,3)=%d\n",max(2,3));printf("max(2.3,5.6,3.1)=%f\n",max(2.3,5.6,3.1));}第1章C++面向对象程序
设计要点1.1.3函数参数C++中函数(包括常规函数和成员函数)参数有四种方式:值参数、常值参数、引用参数和常值引用参数等方式。,一般不用。要注意的是,不同方式的参数(不同方式的返回值也类同)类型,如定义有函数f1(intx),第1章C++面向对象程序设计要点在函数f1(
)中又要调用函数f2(),如果函数f2()的定义是f2(constintx),int和constint为不同的数据类型,从而告知用户数据类型不匹配。int和int&的情况也一样。注意到这一点将可免去许多程序调试中的问题。例1―2函数参数的值参数、引用参数和常值引用参数三种方式。intExampl
e1(inta,intb,intc)//值参数方式{intx,y,z;x=a;y=b;z=c;第1章C++面向对象程序设计要点a=2*a;b=2*b;c=2*c;//函数返回后对应实际参数的值不变return(x+y+z)/3;}intExample2
(int&a,int&b,int&c)//引用参数方式{intx,y,z;x=a;y=b;z=c;a=2*a;b=2*b;c=2*c;//函数返回后对应实际参数的值改变return(x+y+z)/3;}第1章C++面向对象程序
设计要点intExample3(constint&a,constint&b,constint&c)//常值引用参数方式{return(a+b+c)/3;//不允许改变常值引用参数a,b,c的值}第1章C++面向对象程序设计要点引用参数的方法是在类型名
后加符号&,常值引用参数的方法是在引用参数方法的基础上再在函数定义行的最前边加保留字const。对于Example1的值参数方式,在运行时,对应的实际参数的值拷贝给形式参数,当函数终止时,形式参数的值不拷贝回实际参
数。因此,值参数方式的函数调用不会改变对应形式参数的实际参数的值。第1章C++面向对象程序设计要点1.1.4成员函数返回值和函数参数的方式类同,成员函数返回值也有值方式、常值方式、引用方式和常值引用方式等四种方式。当成员函数的返回值为值方式时,允许改变该对象的私有成员数据。注意,成员函数的返回值
为无const标识符的任何数据类型(包括void类型)时即为值方式。第1章C++面向对象程序设计要点例1―3成员函数返回值的值方式和常值方式#include<iostream.h>classTemperature{private:floathighTemp//最高温度floatlowTemp
;//最低温度第1章C++面向对象程序设计要点public:Temperature(floath,floatl){highTemp=h;lowTemp=l;};voidUpdateTemp(floattemp);//成员函数返回值为值方
式floatGetHighTemp(void)const;//成员函数返回值为常值方式floatGetLowTemp(void)const;//成员函数返回值为常值方式};voidTemperature::UpdateTemp
(floattemp){第1章C++面向对象程序设计要点if(temp>highTemp)highTemp=temp;//允许更改私有数据if(temp<lowTemp)lowTemp=temp;//允许
更改私有数据}floatTemperature::GetHighTemp(void)const{returnhighTemp;//不允许更改私有数据}floatTemperature::GetLowTemp(void)const{returnlowTemp;//不
允许更改私有数据}第1章C++面向对象程序设计要点1.2输入输出C++提供了一个层次结构的I/O流类来支持输入输出。I/O流类的类层次结构关系如图1―1所示。流是一个非常形象的术语,每一个流类指定了一类文件和这类文件数据流动的方向。当我们定义一个具体的流类对象时,就确切地指定了这个文件的存储区和
由系统设定的内存缓冲区,以及这个文件在其存储区和内存缓冲区之间的数据流动方向。第1章C++面向对象程序设计要点ios类是基类,它提供了格式、状态信息和错误检测。类ios中没有定义实际的输入和输出操作。实际操作是由派生类istream、ostream等提供的。两种基本的输入
输出方式是:键盘屏幕(默认)输入输出和文件输入输出。第1章C++面向对象程序设计要点istrstreamistream_withassignifstreamiostreamofstreamostream_with
assignostrstreamistreamiosostreamfstreamstrstream图1―1I/O流类的类层次第1章C++面向对象程序设计要点1.2.1键盘屏幕输入输出iostream流类中定义了键盘输入类、屏幕输出类和错误
信息输出类。当iostream流类包含在应用程序中时,cin、cout和cerr分别为键盘输入类、屏幕输出类和错误信息输出类的系统默认对象。cin对象键盘输入的操作符为>>,cout和cerr对象屏幕输出的操作符为<<。第1章C++面向对象程序设计要点
#include<iostream.h>voidmain(void){charc;intn;cout<<"输入n=";cin>>n;cout<<"n="<<n<<endl;}第1章C++面向对象程序设计要点1.2.2文件输入输出调用打
开文件函数时,打开文件函数的参数包括文件名和数据流动的方向,打开文件函数返回文件的开始地址。系统在存储文件时,在其末尾添加有文件结束标记,这样打开文件函数就具体地指定了一个文件在内存中的起始位置、结束位置和数据流动的方向。fstream.h流类中定义了文件输入类
和文件输出类。文件输入类的类名为ifstream,文件输出类的类名为ofstream。第1章C++面向对象程序设计要点#include<fstream.h>#include<iostream.h>#include<stdlib.h>//包含exit()函数Voidmain(void){ifstr
eamfin;//定义fin为ifstream类的对象ofstreamfout;//定义fout为ofstream类的对象fout.open("exam.dat",ios::out);//建立输出文件exam.dat第1章C++面向对象程
序设计要点//输出字符串"wang"和数字50到输出文件exam.dat中(可打开该文件查看)charname[]="wang",name2[10];intage=50,age2;fout<<name<<endl;fout<<age<<endl;f
in.open("exam.dat",ios::in|ios::nocreate);//打开输入文件exam.datif(!fin){第1章C++面向对象程序设计要点cerr<<"不能打开文件exam.dat"<<endl;exit(1);}charc;//
从输入文件exam.dat中输入字符串"wang"和数字50到name2和age2中fin>>name2>>c>>age2;//屏幕输出查看cout<<"name2="<<name2<<endl;cout<<"age2="<<age<<endl;}第1章C++面向对象
程序设计要点1.3类当开发的应用程序的数据类型不是int、float、char等系统支持的基本数据类型时,开发者就需定义自己的数据类型。C++中定义自己的数据类型的面向对象方法是使用类。类是C++支持面向对象程序设计的基础。C++中定义类使用标识
符class,类定义包括类中数据的定义和成员函数的定义。第1章C++面向对象程序设计要点例1―4设计一个人民币类,其方法包括设置、加(+)、加等于(+=),以及输出流操作<<,并用一个主函数验证。#include<iostrea
m.h>#include<stdlib.h>enumsign{minus,plus};//正负数的符号标识//类Money定义部分classMoney//类Money定义第1章C++面向对象程序设计要点{friendostream&operator<<(ostream&out,co
nstMoney&x);//友元private://私有部分longamount;//以分为单位的钱数,amount为类Money的数据部分public://共有部分//构造函数Money(signs=plus,unsigned
longd=0,unsignedlongc=0);//析构函数~Money(){};第1章C++面向对象程序设计要点//共有成员函数BoolSet(signs,unsignedlongd,unsignedlongc);Moneyoperator+(const
Money&x)const;Money&operator+=(constMoney&x){amount+=x.amount;return*this;}//this是默认的当前对象指针};//类Money实现部分Money::Money(signs,unsign
edlongd,unsignedlongc)//构造函数。s为符号,d为元值,c为分值{if(c>99)第1章C++面向对象程序设计要点{cerr<<"分必须小于等于99"<<endl;exit(1);}amount=d*100+c;if(s==minus)amount=-amoun
t;}boolMoney::Set(signs,unsignedlongd,unsignedlongc)//设置函数。s为符号,d为元值,c为分值{if(c>99){cerr<<"分必须小于等于99"<<endl;第1章C++面向对象程序设计要点exit(1);}amoun
t=d*100+c;if(s==minus)amount=-amount;returntrue;}MoneyMoney::operator+(constMoney&x)const//操作符+重载{Moneyy;y.amount=amount+x.amount;returny;}第
1章C++面向对象程序设计要点ostream&operator<<(ostream&out,constMoney&x)//流类的操作符重载。前边不再需标识符friend{Moneytemp=x;//注意临时对象temp绝对不能定义为引用型if(x.amount<0){out
<<′-′;temp=-temp;//temp为x的绝对值}longd=temp/100;//d为amount的元值第1章C++面向对象程序设计要点out<<′¥′<<d<<′.′;intc=temp-d*100;//c为amou
nt的分值if(c<10)out<<′0′;//分值小于10时在十位上添0out<<c;returnout;}//主函数部分voidmain(void){Moneyg,h(plus,3,30),hg;第1章C++面向对象程序设计要点g.Set(minus,2,25);hg=h+
g;//h和g的值均不变g+=h;//g的值被改变cout<<"h+g="<<hg<<endl;cout<<"g="<<g<<endl;}程序运行输出:h+g=¥1.05g=¥1.05下面我们对C++类基本要素的分析讨论将以例1―4
为实例。第1章C++面向对象程序设计要点1.3.1类的存取权限类的数据和成员函数的存取权限分为三种:私有(private)、公有(public)和保护(protected)。在private域中,声明的数据和成员函数构成类的私有部分,私有部分中的数据和成员函数只能由该类对象的成员
函数,以及被声明为友元的函数或声明为友元的类的对象的成员函数访问。第1章C++面向对象程序设计要点在public域中,一般仅声明类的成员函数(有些情况下,也在此域中声明类的数据)。在public域中,声明的类的数据和成员函数构成类的公有部分;公有部
分中的数据和成员函数既允许该类对象的成员函数访问,也允许程序中其他函数或其他类的对象的成员函数访问。因此,一个类的公有部分就构成了这个类的操作界面。外部函数和别的对象通过操作界面对类中的对象进行操作。这就和基本数据类型
中int类数据均通过加(+)、减(-)、乘(*)、除(/)等操作界面来对该数据类型中所有数据进行操作一样。第1章C++面向对象程序设计要点1.3.2构造函数和析构函数构造函数是一种特殊的成员函数。构造函数是用来在内存中建立类的具体对象(即在内存中为该对象分配适当的空间)并
对其进行初始化赋值的成员函数。构造函数的名字必须和类的名字相同,构造函数没有返回值。构造函数允许参数有默认值,当构造函数有默认值时,若定义该类的对象时没有给出初始化值则按默认值处理。例1―4中对象h有初始化值(plus,3,30),对象g和hg没有初始化值,因此对象g和h
g的初始化值为默认值(plus,0,0)。一个类允许有多个构造函数。当一个类有多个构造函数时,系统将根据定义对象时的参数类型和参数个数,选择恰当的构造函数来建立对象和对该对象进行初始化。第1章C++面向对象程序设计要点析构函数是一种当对象被取消时才被自动调用的特
殊函数。当一个对象被取消时,析构函数提供了自动释放由构造函数在内存中建立的该类对象的内存区。析构函数的名字是在类的名字前面加上前缀“~”,析构函数没有返回值。由于在一般情况下建立的对象当被取消时,系统都能自动识别出所
占用的相应的内存区,所以一般情况下析构函数的函数体为空。函数体为空的析构函数可省略。但当对象被取消时系统不能自动识别出所占用的内存区的类,析构函数的函数体就不能为空,此时析构函数就要负责释放对象所占用的内存区。每个类只能有一个析构函数。第1章C++面向对象程序设计要点1.3.3操作
符重载当所设计类的某个成员函数功能和人们熟悉的某个有固定操作符的函数功能类同时,可以用该操作符替换该成员函数名,这称作操作符重载。操作符重载时,操作符前使用标识符operator。对用户来说,操作符重载使类的成员函数的调用更加方便。如例1-4中的加(+)和加等于(+=)成员函数通过操作符重载方便
了用户的调用。也就是说,一个类成员函数的操作符重载就是用一个有固定含义的操作符定义和实现该类的相应成员函数。第1章C++面向对象程序设计要点当调用时该操作符可以看成是该操作符左边对象的成员函数。如例1―4中的g+=hg可看作是加等于(+=)成员函数的对象,h可看作是加等于(+
=)成员函数的参数。操作符重载不仅可以更方便地实现相应成员函数的功能,重载的操作符还具有相应的运算优先级和满足结合律,这是类的成员函数所没有的功能。第1章C++面向对象程序设计要点成员函数的操作符重载时必须满足:
(1)操作符必须满足运算优先级和结合律,以及参数满足相应的操作符对操作数个数的要求,如二元操作加(+)必须有也只能有一个参数作为加数。(2)C++中的所有操作符基本上都可被重载,但逗号操作(,)和条件表达式操作(?:)不允许重载。(3)操
作符重载时不允许参数有默认赋值。(4)当重载的操作符左边的对象属类B,右边的对象属类A时,该重载的操作符应定义为类A的友元;否则类B的对象不能操作类A对象中的数据。第1章C++面向对象程序设计要点操作符重载不仅可以定义为成员函数,也可以定义为一般函数。当类的定义和实现已经编译
完成,而在应用时具体定义的数据类型不支持类的定义和实现中使用的运算符时,定义为一般函数的操作符重载可不改变原先已编译完成的类的定义和实现。一般函数的二元操作符重载需有两个参数,这一点和成员函数的操作符重载不同。3.5.2节的小于(<)操作符的重载就是一个一般函数的例子,此时,原先已编译完成的
类的定义和实现不用改动。第1章C++面向对象程序设计要点1.3.4友元在例1―4中,Money类的输出成员函数和系统的输出流操作(<<)功能类同,因此我们也希望重载输出流操作符<<,但对于如下操作符重载定义ostream&operator<<(ost
ream&out,constMoney&x);由于该操作符左边的对象属类ostream,右边的对象属类Money,类ostream的对象不能存取类Money对象的私有数据amount,因而无法实现期望的输出流操作。第1章C++面向对象程序设计要点
对于上述这种情况,我们可以在类Money的定义中定义类ostream的成员函数(或说操作符)<<是类Money的友元。在C++中一个类的友元可以存取这个类的私有数据。这样当我们在例1―4类Money的定义中有如下友
元定义friendostream&operator<<(ostream&out,constMoney&x);则上述问题即可解决。友元定义使用标识符friend。一个类的友元不仅可以是其他类的成员函数,还可以是外部函数或其他类。当类A的友元是类B时,则类B中的所有成员函数均可存取类A的私有数据
。第1章C++面向对象程序设计要点1.3.5分辨符在例1―4中,类的实现部分中类成员函数名前的符号::称为分辨符。分辨符指定了成员函数所属的类。当类的实现部分和类的定义部分不在一个文件中时,在实现部分的成员函数名前使用分辨符是必要的。此外,在一个有派生类存在的函数或程序中,若派生类和其
基类有同名的成员函数时,在分辨符::前加上派生类名或基类名并放在该成员函数名前就可实现正确的访问。第1章C++面向对象程序设计要点1.3.6内联函数C++类成员函数的实现部分中包括在定义部分的函数称为内联函数。编译系统在遇到内联函数时会将其实现部
分的所有语句直接插入到调用程序中,因而减少了与函数调用和参数传递有关的系统开销,从而可以帮助C++克服在某些面向对象开发环境或开发工具中遇到的执行速度低的难题。由于内联函数增加函数调用的空间开销,因此通常只在实现部分语句较少或在要求系统的响应速度较高时
才使用内联函数。第1章C++面向对象程序设计要点例1―3中类Temperature的构造函数和例1―4中类Money的加等于(+=)操作符重载都是内联成员函数的例子。外部函数的内联函数为在函数定义头部加标识符inline。当成员
函数的实现部分较长时,定义内联函数的方法也是在成员函数头部加标识符inline来实现。第1章C++面向对象程序设计要点1.3.7默认值若定义类时,类的构造函数定义了默认值。定义对象有初始化值时,则该对象取其初始化值;定义对象没有初始化值时,则该对
象取其默认值。在例1―4中,类Money的构造函数定义有默认值(plus,0,0)。类Money的构造函数定义语句为Money(signs=plus,unsignedlongd=0,unsignedlongc=0)第1章C++面向对象程序设计要点1.3.8多态性和虚函数多态性是面向对象程
序设计的一个重要概念。在面向对象语言中,用向一个对象发送消息的方式来完成一系列动作的实现。多态性是指当相同对象收到不同的消息或不同对象收到相同的消息时产生不同的实现动作。C++支持两种多态性:一种是编译时的多态性,另一种是
运行时的多态性。编译时的多态性是通过重载函数来实现的。此时重载的函数有两种:一种是在一个类中说明的重载,此时靠参数的个数和参数的类型不同来区分;另一种是基类成员函数在派生类中的重载,第1章C++面向对象程序设计要点此时也可以靠参数的个数和参数的类型不同来区分,当参数的个数和参数
的类型相同时还可以靠使用“类名::”加以区分。在C++中运行时的多态性是用虚函数来实现的。虚函数是在基类中被说明为virtual,并在派生类中重新定义的成员函数。虚函数允许函数调用与函数体之间的联系在运行时才建立,也就是在运行时才决定当前实际调用的是基类和派生类中哪一个类中的成员函数,
因此,虚函数可实现成员函数的动态重载。第1章C++面向对象程序设计要点例1―5虚函数方法#include<stdio.h>classParent{protected:charversion;public:
Parent(){version=′A′;}//构造函数virtualvoidPrint()//虚函数{printf("\nParentVersion%c",version);}voidTest()//测试继承方式用函数{
printf("\nPublicModeTest!");}};第1章C++面向对象程序设计要点classDerived1:publicParent{private:intinfo;public:Derived1(intnumb
er)//构造函数{version=′1′;info=number;}voidPrint(){printf("\nDerived1info:%d,Version%c",info,version);}};classDerived2:publicParent第1章C++面向对象程序设计要点
{private:intinfo;public:Derived2(intnumber)//构造函数{version=′2′;info=number;}voidPrint(){printf("\nDerived2info:%d,V
ersion%c",info,version);}};第1章C++面向对象程序设计要点voidPrintInfo(Parent&infoHolder){infoHolder.Print();//根据不同的调用对象动态连接不同对象的成员函数}voidmain(void){Pa
rentbase;Derived1d1(10);Derived2d2(20);PrintInfo(base);第1章C++面向对象程序设计要点PrintInfo(d1);PrintInfo(d2);d1.Test();/
/此语句只在public派生方式下允许}程序的输出是:ParentVersionADerived1info:10,Version1Derived2info:20,Version2PublicModeTest!第1章C++面向对象程序设计要点在程序中,通过
外部函数PrintInfo()实现类继承层次中对象的动态绑定。在程序中,若去掉类Parent中成员函数Print()前的virtual,则程序的输出是:ParentVersionAParentVersion1ParentVersion2PublicModeTest!显然,若去掉类
Parent中成员函数Print()前的virtual,则每次调用的都是类Parent的成员函数Print()。第1章C++面向对象程序设计要点1.3.9纯虚函数和抽象类有些基类只表达一些抽象的概念,并不和具体的事物相联系,所以在这些基类中定义某些成员函数是无意义的,但这些基类又必须为他的
派生类提供一个公共接口界面,这样的基类可定义成纯虚函数。纯虚函数是在基类中说明的虚函数,它在基类中没有定义,但要求任何派生类都要定义自己的实现方法。在基类中实现纯虚函数的方法是在函数原型后加上“=0”。例如:第1章C++面向对象程序设计要点classParent{virtualvoidF
unction()=0;//纯虚函数};包含有纯虚函数的类称为抽象类。由于抽象类包含了没有函数定义的纯虚函数,所以不能定义抽象类的对象。当然,在抽象类中也可以定义非纯虚函数供派生类继承。第1章C++面向对象程序设计要点1.3.10派生类继承方式派生类继
承基类时,基类的protected数据和成员函数将作为派生类的protected数据和成员函数。除此之外,派生类定义中的访问控制还定义了基类成员在派生类中的访问权限。访问控制主要有public和private
两种继承方式。第1章C++面向对象程序设计要点在public继承方式中,基类的公有成员成为派生类的公有成员。在例1―5中,派生类Derived1和Derived2对父类Parent的继承是public继承方式。public继承方式的派生类对象
能直接使用基类的所有public的数据和成员函数,因此,例1―5主函数中的d1.Test()调用的是Parent类的成员函数Test();private继承方式使基类的公有成员成为派生类的私有成员。第1章C++面向对象程序设计要点因此,在派
生类中只允许其成员函数调用基类的公有成员函数,private继承方式的例子详见3.3.1节和3.3.2节顺序堆栈类对顺序表类的继承。无论是public继承方式还是private继承方式,基类的私有成员都成为派生
类的不可访问成员。此外,类的友元没有继承性。当基类中有虚函数时,派生类只能是public继承方式,不能是private继承方式。第1章C++面向对象程序设计要点1.3.11结构体C++语言是从C语言发展而来的,面向对象程序设计中的类是结构化程
序设计中结构体的进一步发展,为了使习惯于使用C语言结构体的编程人员能习惯使用C++语言中的类,C++语言中定义结构体和类概念基本相同,惟一不同之处是结构体中都是共有数据成员和共有成员函数,没有私有数据成员和私有成员函数。第1章C++面向对象程序设计要点1.3.12对象具有类类型的变量称
作对象,或者说,对象是类的实例化。例1―5中base、d1和d2就分别是类Parent、Derived1和Derived2的对象。从上述的C++语言对结构体的定义,还可以说,具有类类型或结构体类型的变量称作对象,或者说,对象是类或结构体的实例化。第1章C
++面向对象程序设计要点1.4抽象类型和模板在软件开发和维护过程中需要花费大量的人力和时间,如果能够重复利用以前开发完成的数据结构和算法模块,把它们有选择地组装在新的软件中,将可以大大减少需花费的人力和时间,这就是软件的复用问题。在C++中,实现软件复用的方法主要有抽象类
型法和模板法。第1章C++面向对象程序设计要点1.4.1抽象类型抽象类型方法是类的定义中数据成员的类型使用抽象类型,当应用程序具体包含该类头文件前再对该抽象类型进行具体定义。如例1―3中的类Temperature可定义如下:classTemperature{private
:elemtypehighTempelemtypelowTemp;public:第1章C++面向对象程序设计要点Temperature(floath,floatl){highTemp=h;lowTemp=l;};voidUpdateTemp(floatte
mp);elemtypeGetHighTemp(void)const;elemtypeGetLowTemp(void)const;};假设上述类Temperature的定义和实现放在文件Temperature.h中,当应用程序需要
的精度为float时,则主程序包含该文件的方式为:第1章C++面向对象程序设计要点typedeffloatelemtype;#include"Temperature.h"当应用程序需要的精度为double时,则主程序包含该文件的方式为:typedefdoubleelem
type;#include"Temperature.h"第1章C++面向对象程序设计要点1.4.2模板上述类Temperature定义的模板定义方法是:template<classelemtype>clas
sTemperature{private:elemtypehighTempelemtypelowTemp;public:Temperature(floath,floatl){highTemp=h;lowTemp=l;};第1章C+
+面向对象程序设计要点VoidUpdateTemp(floattemp);ElemtypeGetHighTemp(void)const;ElemtypeGetLowTemp(void)const;};在调用程序中定义具体float类型或double类型对象的方法是:Temp
erature<float>temp;或Temperature<double>temp;