还剩7页未读,继续阅读
文本内容:
第2章c++面向对象程序设计基础在传统的结构化程序设计方法中,数据和处理数据的程序是分离的当对某段程序进行修改或删除时,整个程序中所有与其相关的部分都要进行相应的修改,从而使相应代码的维护变得比较困难为了避免这种情况的发生,c++引用了面向对象的设计方法,它是将数据及处理数据的函数“封装”到一个类中类的实例称为对象在一个对象内,一般只有属于该对象的函数才可以存取该对象的数据这样,其他函数就不会无意中破坏它的内容,从而达到保护和隐藏数据的目的
2.1类和对象抽象,而对象是某一类的实例,因此,类和对象是密切相关的类是面向对象程序设计的核心,它实际上是一种新的数据类型类是对某一类对象的
2.11从结构到类在讨论类之前,先来看一个c语言结构类型示例,该类型的成员有学生姓名,学号、三门课成绩【例EX___eStruct】用结构实现计算平均成绩#includeiostream.hStructSTUSCORE{CharstrName
[12];CharstrStuNo
[9];FloatfScore
[3];};FloatGet__erageSTUSCOREone{returnfloatone.fscore
[0]+one.fscore
[1]+one.fscore
[2]/
3.0;}Void__in{STUSCOREone={“liming””21020501”{809065}};Coutone.strName”的平均成绩为”Get__erageone”\n”;}运行结果如下Liming的平均成绩为
78.3333从上述示例可以看出,学生三门课的平均成绩是通过程序中的全局函数Get__erage来计算的,那么能否将此函数作为结构的成员呢?这时就需要“类”了
2.
1.2类的定义类的定义一般地分为声明部分和实现部分声明部分用来声明该类中的成员,包含数据成员的声明和成员函数的声明成员函数是用来对数据成员进行操作的,又称为“方法”实现部分用来对成员函数进行定义概括的说,声明部分将告诉使用者“干什么”而实现部分是告诉使用者“怎么干”C++中定义类的一般格式如下Class类名{Private:[私有数据和函数]Public:[公有数据和函数]};各个成员函数的实现其中,class是定义类的关键字,class的后面是用户定义的类名,通常用大写的C字母开始的标识符作为类名C用来表示类(Class),以与对象、函数及其他数据类型相区别类中的数据和函数是类的成员,分别称为数据成员和成员函数需要说明的是,由于数据成员是用变量来描述的,因此数据成员又可称为“成员变量”类中的关键字public和private声明了类中的成员和程序其他部分的关系对于public成员来说,他们是公有的,能被外面的程序访问;对于private类成员函数来说,他们是私有的,只能由类中的函数来使用,而不能被外面的程序所访问各个成员函数的实现是类对于中的实现部分,这部分包含所有在类体中声明的函数的定义(即对成员函数的实现)如果一个成员函数在类体中定义,实现部分将不出现如果所有的成员函数都在类体中定义,则实现部分可以省略需要说明的是,当类的成员函数的函数体在类的外部定义时,必须由作用域运算符“::”来通知编译系统该函数所属的类下面的示例就是将例Ex___eStruct的功能用类来实现#includeiostream.h#includestring.hclassCStuScore{charstrName
[12];//姓名charstrStuNo
[9];//学号voidSetScorefloats0floats1floats2//成员函数设置三门课成绩{fScore
[0]=s0;fScore
[1]=s1;fScore
[2]=s2;}floatGet__erage;private://私有类型声明floatfScore
[3];//三门课程成绩};//注意分号不能省略floatCStuScore::Get__erage{returnfloatfScore
[0]+fScore
[1]+fScore
[2]/
3.0;}void__in{CStuScoreone;strcpyone.strNameLiMing;strcpyone.strStuNo21020501;one.SetScore809066;coutone.strName的平均成绩为one.Get__erage\n;}上述CStuScore类中包含了SetScore和Get__erage成员函数,分别用来输入成绩和返回计算后的平均成绩其中,SetScore成员函数是在类体中定义的,而Get__erage是类的外部定义的,注意两者的区别另外,定义类时还应注意1)在“public:”或“private:”后面定义的所有成员都是公有或私有的,直到下一个“public:”或“private:”出现为止若成员前面没有类似的“public:”或“private:”,则所定义的成员是private(私有的),这是类的默认设置2)关键字public和private可以在类中出现多次,且前后的顺序没有关系但最好先声明公有成员再声明私有成员,因为公有成员是用户最关心的3)除了public和private外,关键字protected也可修饰成员的类型,它与private基本相似,但在类的继承时有所不同4)数据成员的类型可以是任意的,包含整型、浮点型、字符型、数组、指针等,也可以是另一个类的对象,但不允许对所定义的成员变量进行初始化
2.1.3对象的定义一个类定义后,就可以定义该类的对象,如下面的格式类名对象名列表其中,类名是已定义过的标识符,对象名可以有一个或多个,多个时要用逗号分隔被定义的对象既可以是一个普通对象,也可以是一个数组对象或指针对象例如CstuScoreone*twothree
[3];这时,one是类CStuScore的一个普通对象,two和three分别是该类的一个指针对象和数组对象一个对象的成员就是该对象的类所对定义的成员,引用(访问)时可用下列方式对象名.成员名对象名.成员名(参数表)前者用来表示引用数据成员,后者用来表示引用成员函数“.”是一个成员运算符,用来引用对象的成员如One.strNamethree
[0].Get__erage;对于指针对象的成员引用可用下列方式对象指针名-成员名对象指针名-成员名(参数表)“-”也是一个成员运算符,它与“.”运算符的区别是“-”用来访问指针对象的成员,而“.”用来访问一般对象的成员需要说明的是,下面的两种表示是等价的对象指针名-成员名(对象指针名).成员名这对于成员函数也适用,例如two-Get__erage和(*two).Get__erage是等价的,由于成员运算符“.”的优先级比取内容运算符“*”高,因此需要在“*two”两边加上括号从上可以看到,c语言的结构类型和c++的类在很大程度上都是相同的正因为如此,c++对结构类型进行了扩展,使其成为类的一种特殊形式也就是说,在c++的结构类型定义中除了struct和class关键字不同外,其余都相同只不过,若结构成员前面没有“public:”或“private:”则所定义的成员是public(公有)
2.2类的成员及特性与c语言结构类型相比,c++的类有其独特的成员函数及特性,本节就来阐述这些内容构造函数前面已提及,在类的定义中是不能对数据成员进行初始化的为了能给数据成员自动设置某些初始值,这时就要使用类的特殊成员函数——构造函数构造函数的最大特点是在对象建立时它会被自动执行,因此用于变量、对象的初始化代码一般放在构造函数中C++规定构造函数必须与相应的类同名,它可以带参数,也可以不带参数,它与一般的成员函数定义相同,而且可以重载,即有多个构造函数出现但不能指定返回值的类型,也不能指定为void类型例如ClassCStuScore{Public:CStuScorecharstr
[12]//第一个构造函数{StrcpystrNamestr;}CStuScorecharstr
[12]charstrNo
[9]//第二个构造函数{StrcpystrNamestr;StrcpystrstuNostrNo;}CharstrName
[12];//姓名CharstrstuNo
[9];//学号…}需要说明的是1)程序中的strcpy是C++的一个库函数,用来__字符串,使用时需要头文件string.h2)实际上,在类定义时,如果没有定义构造任何构造函数,则编译器自动为类生成一个不带任何参数的默认果构造函数对于CStuScore类来说,默认构造函数的形式如下CStuScore//默认构造函数的形式{}3)由于构造函数的参数只能在定义对象时指定,因此有CStuScoreoOne“liming”;它是自动调用第一个构造函数,使得strName内容为“liming”若有CStuScoreoTwo;则编译器会给出错误的提示,因为类CStuScore中已经定义了构造函数,默认构造函数将不在显示调用,因此在类中还要给出默认构造函数的定义,这样才能对oTwo进行初始化,此时对象的所有数据成员(成员变量)都被初始化为零或空析构函数与构造函数相对应的另一种特殊的C++成员函数是析构函数,它的功能是用来释放一个对象,在对象删除前,用它来做一些清理工作,它与构造函数的功能正好相反析构函数也要与相应的类同名,并在名称前面加上一个“~”每一个类只有唯一的一个析构函数,没有任何参数,也不返回任何值,也不能被重载例如ClassCStuScore{Public:…~CStuScore{}//析构函数…}同样,如果一个类中没有定义构造函数时,则编译系统也会为类自动生成一个默认析构函数,其格式如下,(以类CStuScore为例)~CStuScore//默认析构函数的形式{}需要说明的是,析构函数只有在下列两种情况下才会被自动调用1)当对象定义在一个函数体中,该函数调用结束后,析构函数被自动调用2)用new为对象分配动态内存后,当使用delete释放对象时,析构函数被自动调用对象成员初始化前面程序中所定义的类基本都是一个,但在实际应用中往往需要多个类,这时就可能把一个已定义类的对象作为另一个类的成员(称为对象成员)为了能对这些对象成员进行初始化,C++允许采用这样的构造函数定义格式类名::构造函数名(形参表)对象1(参数表),对象2(参数表),…,对象n(参数表){}其中,对象
1、对象2……对象n就是该类使用的其他类的对象,冒号“”后面的列表称为成员初始化列表下面来看一个示例【例Ex_lnitMultO__ect】对象成员的初始化#includeiostream.hclassCPoint{public:CPointintxinty{nPosX=x;nPosY=y;}voidShowPos{cout当前位置x=nPosXy=nPosYendl;}private:intnPosXnPosY;};classCSize{public:CSizeintlintw{nLength=lnWidth=w;}voidShowSize{cout当前大小:l=nLengthw=nWidthendl;}private:intnLengthnWidth;};classCRect{public:CRectintleftinttopintrightintbottom;voidShow{pt__nter.ShowPos;size.ShowSize;}private:CPointpt__nter;CSizesize;};CRect::CRectintleftinttopintrightintbottom:sizeright-leftbottom-toppt__nterleft+right/2top+bottom/2{}void__in{CRectrc1010080250;rc.Show;}运行结果为当前位置x=45,y=175当前大小l=70w=150在代码中,CRect类私有成员——CPoint类对象pt__nter和CSize类对象size的初始化是在CRect类构造函数实现时进行的需要说明的是1)类的对象成员必须初始化,但不能将对象成员直接在构造函数体内进行初始化,例如下面的初始化是不可以的CRectintleftinttopintrightintbottom{pt__nter=CPointleft+right/2top+bottom/2size=right-leftbottom-top;}2对象成员初始化时,必须有相应的构造函数,且多个对象成员的构造次序不是按初始化成员列表的顺序,而是按各类声明的先后次序进行的,从上例的运行结果可以得到证明3)对象成员初始化也可在类构造函数定义时进行例如classCRect{public:CRectintleftinttopintrightintbottom:sizeright-leftbottom-toppt__nterleft+right/2top+bottom/2{}voidShow{pt__nter.ShowPos;size.ShowSize;}private:CPointpt__nter;CSizesize;};4事实上,成员初始化列表也可用于类中的普通数据成员的初始化例如ClassCOne{Inta;Public:Coneintx:ax//注意不能是Coneintx:a=x{ }};常类型常类型是指使用类型修饰符const说明的类型,由于常类型的变量或对象的值是不能被更新的,因此定义或声明常类型时必须进行初始化
1.常对象常对象是指对象常量,定义格式如下类名const对象名定义常对象时,同样要进行初始化,并且该对象不能再被更新,修饰符const可以放在类名后面,也可以放在类名前面例如ClassCone{Public:Coneintaintb{x=a;y=b;}…Private:Intxy;};constConea34;Coneconstb56;其中,a和b都是Cone对象常量,初始化后就不能再被更新
2.常成员函数使用const关键字进行说明的成员函数,称为常成员函数只有常成员函数才有资格操作常量或常函数常成员函数说明格式如下类型说明符函数名(参数表)const;其中,const是加在函数声明后面的类型修饰符,由于它是函数类型的一个组成部分,因此在函数实现部分也要带const关键字例如【例Ex_ConstFunc】常成员函数的使用#includeiostream.hclassCOne{public:COneintaintb{x=a;y=b;}voidprint;voidprintconst;//声明常成员函数private:intxy;};voidCOne::print{coutxyendl;}voidCOne::printconst{cout使用常成员函数xyendl;}void__in{COneone54;one.print;constCOnetwo2052;two.print;}运行结果为54使用常成员函数2052该程序的类Cone声明了两个重载成员函数,一个带const,一个不带语句“one.print;”调用成员函数“voidprint;”,而“two.print;”调用常成员函数“voidprintconst;”需要说明的是,在VisualC++中,常成员函数还可以理解成是一个“只读”函数,它既不能更改数据成员的值,也不能调用那些引起数据成员值变化的成员函数,而只能调用const成员函数例如classCDate{public:CDateintmnintdyintyr;//构造函数intgetMonthconst;//常成员函数voidsetMonthintmn;//一般成员函数intmonth;//数据成员};IntCDate::getMonthconst{returnmonth;//不能修改数据成员的值,只有一个返回值}voidCDate::setMonthintmn{month=mn;//可以使用赋值等语句,修改数据成员的值}
3.常数据成员类型修饰符不仅可以说明成员函数,也可以说明数据成员由于const类型对象必须进行初始化,并且不能更新,因此,在类中声明const数据成员后,只能通过构造函数成员初始化方式来对常数据成员初始化例如【Ex_ConstDate】常数据成员的使用#includeiostream.hclassCOne{public:COneinta:xarx//常数据成员的初始化{}voidprint;constintr;//引用类型的常数据成员private:constintx;//常数据成员};voidCOne::print{coutx=xr=rendl;}void__in{COneone100;one.print;}。