面向?qū)ο驝 第四章_第1頁
面向?qū)ο驝 第四章_第2頁
面向?qū)ο驝 第四章_第3頁
面向?qū)ο驝 第四章_第4頁
面向?qū)ο驝 第四章_第5頁
已閱讀5頁,還剩103頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

面向?qū)ο驝第四章第1頁,共108頁,2023年,2月20日,星期四4.1.1定義類像枚舉和結(jié)構(gòu)一樣,類也是一種用戶自己構(gòu)造的數(shù)據(jù)類型并遵循C++的規(guī)定。類也要先聲明后使用;不管聲明的內(nèi)容是否相同,聲明同一個名字的兩個類是錯誤的,類是具有惟一標識符的實體;在類中聲明的任何成員不能使用extern、auto和register關(guān)鍵字進行修飾;類中聲明的變量屬于該類,在某些情況下,變量可以被該類的不同實例所共享。類和其他數(shù)據(jù)類型不同的是,組成這種類型的不僅可以有數(shù)據(jù),而且可以有對數(shù)據(jù)進行操作的函數(shù),它們分別叫做類的數(shù)據(jù)成員和類的成員函數(shù),而且不能在類聲明中對數(shù)據(jù)成員使用表達式進行初始化。第2頁,共108頁,2023年,2月20日,星期四1.聲明類類是對一組性質(zhì)相同對象的程序描述。在C++中聲明類的一般形式為:class類名{private:私有數(shù)據(jù)和函數(shù)public:公有數(shù)據(jù)和函數(shù)protected:保護數(shù)據(jù)和函數(shù)};類聲明以關(guān)鍵字class開始,其后跟類名。類所聲明的內(nèi)容用花括號括起來,右花括號后的分號作為類聲明語句的結(jié)束標志。這一對花括號“{}”之間的內(nèi)容稱為類體。第3頁,共108頁,2023年,2月20日,星期四類中定義的數(shù)據(jù)和函數(shù)稱為這個類的成員(數(shù)據(jù)成員和成員函數(shù))。類成員均具有一個屬性,叫做訪問權(quán)限,通過它前面的關(guān)鍵字來定義。關(guān)鍵字private、public和protected以后的成員的訪問權(quán)限分別是私有、公有和保護的,把這些成員分別叫做私有成員、公有成員和保護成員。訪問權(quán)限用于控制對象的某個成員在程序中的可訪問性,如果沒有使用關(guān)鍵字,則所有成員默認聲明為private權(quán)限。這些關(guān)鍵字的使用順序和次數(shù)也都是任意的。第4頁,共108頁,2023年,2月20日,星期四【例4.1】描述點的Point類。classPoint{//類名Pointprivate://聲明為私有訪問權(quán)限intx,y;//私有數(shù)據(jù)成員public://聲明為公有訪問權(quán)限voidSetxy(inta,intb);//無返回值的公有成員函數(shù)voidMove(inta,intb);//無返回值的公有成員函數(shù)voidDisplay();//無返回值的公有成員函數(shù)intGetx();//返回值為int的公有成員函數(shù)intGety();//返回值為int的公有成員函數(shù)};//類聲明以分號結(jié)束x和y是私有成員Setxy、Display、Move、Getx和Gety是公有成員因為只是聲明函數(shù),所以可只給出函數(shù)原型?!纠?.2】是其等效的聲明方式。第5頁,共108頁,2023年,2月20日,星期四【例4.2】使用默認關(guān)鍵字及改變關(guān)鍵字順序和次數(shù)的Point類。#include<iostream>usingnamespacestd;classPoint{//類名Pointintx;//默認私有數(shù)據(jù)成員public://聲明為公有訪問權(quán)限voidSetxy(int,int);//無返回值的公有成員函數(shù)的函數(shù)原型voidMove(int,int);//無返回值的公有成員函數(shù)的函數(shù)原型voidDisplay();//無返回值的公有成員函數(shù)的函數(shù)原型intGetx();//返回值為int的公有成員函數(shù)的函數(shù)原型intGety();//返回值為int的公有成員函數(shù)的函數(shù)原型private://聲明為私有訪問權(quán)限inty;//私有數(shù)據(jù)成員};//類定義以分號結(jié)束由此可見,成員函數(shù)聲明的規(guī)則與第3章所述的函數(shù)聲明規(guī)則相同。

第6頁,共108頁,2023年,2月20日,星期四2.定義成員函數(shù)類中說明的成員函數(shù)用來對數(shù)據(jù)成員進行操作。在類中只對這些成員函數(shù)進行了函數(shù)聲明,還必須在程序中實現(xiàn)這些成員函數(shù)。定義成員函數(shù)的一般形式為:

返回類型類名::成員函數(shù)名(參數(shù)列表){成員函數(shù)的函數(shù)體//內(nèi)部實現(xiàn)}其中“::”是作用域運算符,“類名”是成員函數(shù)所屬類的名字,“::”用于表明其后的成員函數(shù)是屬于這個特定的類?!邦惷?:成員函數(shù)名”的意思就是對屬于“類名”的成員函數(shù)進行定義,而“返回類型”則是這個成員函數(shù)返回值的類型。第7頁,共108頁,2023年,2月20日,星期四定義成員函數(shù)的函數(shù)體。例如Setxy定義如下:voidPoint::Setxy(inta,intb){x=a;y=b;}定義Point的函數(shù)成員Setxy(inta,intb),該成員帶有兩個整型參數(shù),函數(shù)沒有返回值(void)。voidPoint::Move(inta,intb){x=x+a;y=y+b;}voidPoint::Display(){cout<<x<<","<<y<<endl;}intPoint::Getx(){returnx;}intPoint::Gety(){returny;}第8頁,共108頁,2023年,2月20日,星期四

可以使用關(guān)鍵字inline將成員函數(shù)定義為內(nèi)聯(lián)函數(shù),例如:inlineintPoint::Getx(){returnx;}如果在聲明類的同時,在類體內(nèi)給出成員函數(shù)的定義,則默認為內(nèi)聯(lián)函數(shù)。例如在類中將聲明Getx的語句“intGetx();”改為“intGetx(){returnx;}”,則Getx為內(nèi)聯(lián)函數(shù)。一般直接在類體內(nèi)給出簡單成員函數(shù)的定義。有些成員函數(shù)的實現(xiàn)方式不止一種,例如voidPoint::Display(){cout<<Getx()<<","<<Gety()<<endl;}是調(diào)用成員函數(shù)Getx()和Gety()實現(xiàn)的,它們使用了cout流,應(yīng)在定義之前包含如下語句:#include<iostream>usingnamespacestd;第9頁,共108頁,2023年,2月20日,星期四3.數(shù)據(jù)成員的賦值不能在類體內(nèi)給數(shù)據(jù)成員賦值,即下面的方法是錯誤的:ClassPoint{intx=25,y=56;……};當然,在類體外面就更不允許了。數(shù)據(jù)成員的具體值是用來描述對象的屬性的。只有產(chǎn)生了一個具體的對象,這些數(shù)據(jù)值才有意義,所以又稱對象的初值或?qū)ο蟪跏蓟?。假設(shè)已經(jīng)有了一個對象A,則可使用“.”運算符調(diào)用成員函數(shù)Setxy賦初值。例如:A.Setxy(25,56);將對象A的數(shù)據(jù)成員x和y分別賦給25和56,即A.x=25,A.y=56。

真正的初始化是使用與Point同名的構(gòu)造函數(shù)Point(int,int)實現(xiàn)的。產(chǎn)生Point對象的語句:PointA(25,56);第10頁,共108頁,2023年,2月20日,星期四4.1.2使用類的對象及指針Point類是用戶定義的一種類型,使用Point在程序中聲明變量,具有Point類的類型的變量被稱為Point的對象。只有產(chǎn)生類的對象,才能使用這些數(shù)據(jù)和成員函數(shù)。類Point不僅可以聲明對象,還可以聲明對象的引用和對象的指針,語法與基本數(shù)據(jù)類型一樣。PointA,B;//定義Point類型的對象A和BPoint*p=&A;//定義指向?qū)ο驛的Point類型的指針Point&R=B;//定義R為Point類型對象B的引用

第11頁,共108頁,2023年,2月20日,星期四對象和引用都使用運算符“.”訪問對象的成員,指針則使用“->”運算符。例如:A.Setxy(25,88);//為對象A設(shè)置初值p->Display();//顯示指針p所指對象A的數(shù)據(jù)成員//A.x和A.y之值R.Display();//顯示對象B的數(shù)據(jù)成員B.x和B.y之值【例4.3】根據(jù)上面對Point類的定義,演示使用Point類的對象。voidprint(Pointa)//使用Point的對象a作為函數(shù)參數(shù){a.Display();//顯示對象a的數(shù)據(jù)成員的值}voidmain()第12頁,共108頁,2023年,2月20日,星期四{ PointA,B;//聲明對象 A.Setxy(25,55);//為對象A賦初值 B=A;//B的數(shù)據(jù)成員取A的數(shù)據(jù)成員之值 A.Display();//顯示A的數(shù)據(jù)成員 A.Move(-10,20);//移動A print(A);//等價于A.Display(); print(B);//等價于B.Display() cout<<A.Getx()<<endl;//只能使用A.Getx(),//不能使用A.x}本例中的print函數(shù)使用Point的對象作為參數(shù)。C++推薦使用下面的引用的形式:voidprint(Point&a)//使用對象的引用做為函數(shù)參數(shù){a.Display();}//顯示引用對象a的數(shù)據(jù)成員之值第13頁,共108頁,2023年,2月20日,星期四對象A移動之后,對象B仍為原來的值,所以輸出如下:25,55//原來的A和B15,75//新的A25,55//原來的B15//A.Getx()返回對象A的數(shù)據(jù)成員x的之值如果在print函數(shù)或主函數(shù)里使用如下語句,則產(chǎn)生錯誤:cout<<A.x<<","<<A.y<<endl;//錯誤!第14頁,共108頁,2023年,2月20日,星期四暫不涉及還沒有介紹的保護成員,可以歸納出如下規(guī)律:(1)類的成員函數(shù)可以直接使用自己類的私有成員(數(shù)據(jù)成員和成員函數(shù))。(2)類外面的函數(shù)不能直接訪問類的私有成員(數(shù)據(jù)成員和成員函數(shù))。(3)類外面的函數(shù)只能通過類的對象使用該類的公有成員函數(shù),例如print和main函數(shù)。(4)類對象A和B的成員函數(shù)的代碼一樣,不同對象的區(qū)別是屬性的取值。第15頁,共108頁,2023年,2月20日,星期四在程序運行時,通過為對象分配內(nèi)存來創(chuàng)建對象。在創(chuàng)建對象時,使用類作為樣板,故稱對象為類的實例。A和B兩個對象占據(jù)內(nèi)存中的不同區(qū)域。A的數(shù)據(jù)是A.x和A.y,而B的數(shù)據(jù)是B.x和B.y,它們各有表現(xiàn)自己的屬性數(shù)據(jù),但用來操作數(shù)據(jù)的代碼均是一樣的,例如A.Getx()和B.Getx()的代碼一樣。為節(jié)省內(nèi)存,在建立對象時,只分配用于保存數(shù)據(jù)的內(nèi)存,代碼為每個對象共享。類中定義的代碼被放在計算機內(nèi)存的一個公用區(qū)中供該類的所有對象共享。

第16頁,共108頁,2023年,2月20日,星期四表4.1類Point的兩個實例A和B對象A對象B對象成員對象成員分配內(nèi)存內(nèi)容對象成員對象成員分配內(nèi)存內(nèi)容A.xA.x的值B.xB.x的值A(chǔ).yA.y的值B.yB.y的值A(chǔ).Setxy(int,int)Setxy函數(shù)代碼B.Setxy(int,int);Setxy函數(shù)代碼A.Move(int,int)Move函數(shù)代碼B.Move(int,int);Move函數(shù)代碼A.Display()Display函數(shù)代碼B.Display()Display函數(shù)代碼A.Getx()Getx函數(shù)代碼B.Getx()Getx函數(shù)代碼A.Gety()Gety函數(shù)代碼B.Gety()Gety函數(shù)代碼第17頁,共108頁,2023年,2月20日,星期四可以通過類對象的指針訪問對象的成員。定義類對象指針的語法如下:

類名*對象指針名;對象指針名=對象的地址;也可以直接進行初始化。例如:類名*對象指針名=對象的地址;類對象的指針可以通過“->”運算符訪問對象的成員,即:

對象指針名->對象成員名第18頁,共108頁,2023年,2月20日,星期四【例4.4】演示使用內(nèi)聯(lián)函數(shù)定義Point類及使用Point類指針和引用的完整例子。#include<iostream>//包含頭文件usingnamespacestd;//聲明命名空間classPoint{//使用內(nèi)聯(lián)函數(shù)定義類Pointprivate://聲明為私有訪問權(quán)限 intx,y;//私有數(shù)據(jù)成員public://聲明為公有訪問權(quán)限voidSetxy(inta,intb)//無返回值的內(nèi)聯(lián)公有成員函數(shù){x=a;y=b;}voidMove(inta,intb)//無返回值的內(nèi)聯(lián)公有成員函數(shù){x=x+a;y=y+b;}voidDisplay()//無返回值的內(nèi)聯(lián)公有成員函數(shù){cout<<x<<","<<y<<endl;}intGetx(){returnx;}//返回值為int的內(nèi)聯(lián)公有成員函數(shù)intGety(){returny;}//返回值為int的內(nèi)聯(lián)公有成員函數(shù)};//類定義以分號結(jié)束voidprint(Point*a)//類指針作為print函數(shù)的參數(shù)定義重載函數(shù){a->Display();}voidprint(Point&a)//類引用作為print函數(shù)的參數(shù)定義重載函數(shù){a.Display();}第19頁,共108頁,2023年,2月20日,星期四voidmain()//主函數(shù){PointA,B,*p;//聲明對象和指針Point&RA=A;//聲明對象RA引用對象AA.Setxy(25,55);//使用成員函數(shù)為對象A賦值B=A;//使用賦值運算符為對象B賦值p=&B;//類Point的指針指向?qū)ο驜p->Setxy(112,115);//使用指針調(diào)用函數(shù)Setxy//重新設(shè)置B的值print(p);//傳遞指針顯示對象B的屬性p->Display();//再次顯示對象B的屬性RA.Move(-80,23);//引用對象RA調(diào)用Move函數(shù)print(A);//驗證RA和A同步變化print(&A);//直接傳遞A的地址作為指針參數(shù)}第20頁,共108頁,2023年,2月20日,星期四程序運行結(jié)果如下:112,115112,115-55,78-55,78由此可見,使用對象和對象指針的效果一樣。第21頁,共108頁,2023年,2月20日,星期四4.1.4數(shù)據(jù)封裝面向?qū)ο蟮某绦蛟O(shè)計,是通過為數(shù)據(jù)和代碼建立分塊的內(nèi)存區(qū)域,以便提供對程序進行模塊化的一種程序設(shè)計方法,這些模塊可以被用做樣板,在需要時再建立其副本。根據(jù)這個定義,對象是計算機內(nèi)存中的一塊區(qū)域,通過將內(nèi)存分塊,每個模塊(即對象)在功能上保持相對獨立。另外,定義也表明如下問題:①這些內(nèi)存塊中不但存儲數(shù)據(jù),而且也存儲代碼,這對保證對象是受保護的這一點很重要。對象保護它自己不受未知的外部事件的影響,從而使自己的數(shù)據(jù)和功能不會因此遭到破壞。第22頁,共108頁,2023年,2月20日,星期四②這些內(nèi)存塊的結(jié)構(gòu)可被用做樣板產(chǎn)生對象的更多副本。例如,一旦定義了一個窗口對象,只要內(nèi)存允許,就可以建立許多這樣的對象。在面向?qū)ο蟮某绦蛑校瑢ο蟮男袨橹挥邢驅(qū)ο蟀l(fā)送消息才能引用,例如通過Display發(fā)出顯示消息,所以說面向?qū)ο笫窍⑻幚頇C制。面向?qū)ο缶褪菍⑹澜缈闯墒怯梢唤M彼此相關(guān)并能相互通信的實體即對象組成的。程序中的對象映射現(xiàn)實世界中的對象。

第23頁,共108頁,2023年,2月20日,星期四C++對其對象的數(shù)據(jù)成員和成員函數(shù)的訪問是通過訪問控制權(quán)限來限制的。private是限制類之外的函數(shù)的訪問權(quán)。只要將數(shù)據(jù)成員或成員函數(shù)使用private限定,就設(shè)定了一道防線。它還必須留下與外面打交道的接口,這通過具有public權(quán)限的成員函數(shù)實現(xiàn)。在C++中,數(shù)據(jù)封裝是通過類來實現(xiàn)的。在類中指定了各成員的訪問權(quán)限。一般情況下:將數(shù)據(jù)成員說明為私有的,以便隱藏數(shù)據(jù);將部分成員函數(shù)說明為公有的,用于提供外界和這個類的對象相互作用的接口(界面),從而使得其他函數(shù)(例如main函數(shù))也可以訪問和處理該類的對象。對于那些僅是為支持公有函數(shù)的實現(xiàn)而不作為對象界面的成員函數(shù),也將它們說明為私有的。第24頁,共108頁,2023年,2月20日,星期四4.2構(gòu)造函數(shù)建立一個對象時,對象的狀態(tài)(數(shù)據(jù)成員的取值)是不確定的。為了使對象的狀態(tài)確定,必須對其進行正確的初始化。C++有一個稱為構(gòu)造函數(shù)的特殊成員函數(shù),它可自動進行對象的初始化。第25頁,共108頁,2023年,2月20日,星期四4.2.1默認構(gòu)造函數(shù)當沒有為一個類定義任何構(gòu)造函數(shù)的情況下,C++編譯器總要自動建立一個不帶參數(shù)的構(gòu)造函數(shù)。例如,如果在上面的例子中沒有為Point類定義任何構(gòu)造函數(shù),則C++編譯器要為它產(chǎn)生一個默認構(gòu)造函數(shù),這個默認構(gòu)造函數(shù)具有下面這種形式:Point::Point(){}即它的函數(shù)體是空的。因此,當建立Point類的一個對象時,對象的狀態(tài)是不確定的,即沒有被初始化。

第26頁,共108頁,2023年,2月20日,星期四

一旦程序定義了自己的構(gòu)造函數(shù),系統(tǒng)就不再提供這個默認構(gòu)造函數(shù)。如果程序員沒有定義一個無參數(shù)的構(gòu)造函數(shù),但又聲明了一個沒有初始化的對象(如“PointA;”),則因系統(tǒng)已經(jīng)不再提供默認構(gòu)造函數(shù),編譯就會出錯?!澳J”也稱為“缺省”,本書統(tǒng)一使用“默認”。不帶參數(shù)的構(gòu)造函數(shù)又稱作默認構(gòu)造函數(shù)。如果只聲明對象數(shù)組(即不提供初值),因為每個元素對象均需要調(diào)用一次默認構(gòu)造函數(shù)來為自己初始化,所以必須要求有一個默認構(gòu)造函數(shù)。

第27頁,共108頁,2023年,2月20日,星期四4.2.2定義構(gòu)造函數(shù)1.構(gòu)造函數(shù)的定義和使用方法構(gòu)造函數(shù)的作用是在對象被創(chuàng)建時使用特定的值構(gòu)造對象,或者說將對象初始化為一個特定的狀態(tài)。在對象創(chuàng)建時由系統(tǒng)自動調(diào)用。如果程序中未聲明,則系統(tǒng)自動產(chǎn)生出一個默認形式的構(gòu)造函數(shù)允許為內(nèi)聯(lián)函數(shù)、重載函數(shù)、帶默認形參值的函數(shù)。第28頁,共108頁,2023年,2月20日,星期四構(gòu)造函數(shù)的特點構(gòu)造函數(shù)名與類名相同;沒有返回值;定義在public下;構(gòu)造函數(shù)由系統(tǒng)自動調(diào)用;若不顯式定義,系統(tǒng)自動生成一個不帶參數(shù)的構(gòu)造函數(shù);顯式定義了構(gòu)造函數(shù)后,默認的構(gòu)造函數(shù)不起作用;構(gòu)造函數(shù)可以重載;第29頁,共108頁,2023年,2月20日,星期四【例4.5】構(gòu)造函數(shù)的定義和執(zhí)行過程實例程序。#include<iostream>usingnamespacestd;classPoint{private:intx,y;public:Point();//聲明不帶參數(shù)的構(gòu)造函數(shù) Point(int,int);//聲明帶2個參數(shù)的構(gòu)造函數(shù)};Point::Point():x(0),y(0)//定義不帶參數(shù)的構(gòu)造函數(shù){cout<<"Initializingdefault"<<endl;}//定義帶2個參數(shù)的構(gòu)造函數(shù)Point::Point(inta,intb):x(a),y(b){cout<<"Initializing"<<a<<","<<b<<endl;}第30頁,共108頁,2023年,2月20日,星期四voidmain(){PointA;//使用不帶參數(shù)的構(gòu)造函數(shù)產(chǎn)生對象APointB(15,25);//使用帶參數(shù)的構(gòu)造函數(shù)產(chǎn)生對象BPointc[2];//使用不帶參數(shù)的構(gòu)造函數(shù)產(chǎn)生對象數(shù)組CPointD[2]={Point(5,7),Point(8,12)};//使用帶參數(shù)//的構(gòu)造函數(shù)產(chǎn)生對象數(shù)組D}第31頁,共108頁,2023年,2月20日,星期四程序輸出結(jié)果如下:InitializingdefaultInitializing15,25InitializingdefaultInitializingdefaultInitializing5,7Initializing8,12程序中和Point類同名的兩個成員函數(shù)是構(gòu)造函數(shù):一個不帶參數(shù),另一個帶有2個參數(shù)。第32頁,共108頁,2023年,2月20日,星期四構(gòu)造函數(shù)可以通過構(gòu)造函數(shù)的初始化列表給其數(shù)據(jù)成員賦值Point::Point(inta,intb):x(a),y(b)完成“x=a,y=b”的功能,它與下面的方法等價:Point::Point(int,intb){x=a;y=b;cout<<"Initializing"<<a<<","<<b<<endl;}第33頁,共108頁,2023年,2月20日,星期四構(gòu)造函數(shù)在類體里的聲明形式如下:

類名(形參1,形參2,…形參n);//可以沒有形參構(gòu)造函數(shù)在類體外定義??梢允褂贸跏蓟斜砘蛘咴跇?gòu)造函數(shù)的函數(shù)體內(nèi)定義數(shù)據(jù)成員的初值。假設(shè)數(shù)據(jù)成員為x1,x2,…,xn,則有如下兩種形式:

類名::類名(形參1,形參2,…形參n):x1(形參1),x2(形參2),…,xn(形參n){}類名::類名(形參1,形參2,…形參n){x1=形參1;x2=形參2;……xn=形參n;}構(gòu)造函數(shù)的參數(shù)是無順序排列,只要保證相互的對應(yīng)順序即可??墒褂媚J參數(shù)或重載。第34頁,共108頁,2023年,2月20日,星期四當聲明一個外部對象時,外部對象只是引用在其他地方聲明的對象,程序并不為外部對象說明調(diào)用構(gòu)造函數(shù)。如果是全局對象或靜態(tài)對象,在main函數(shù)執(zhí)行之前要調(diào)用它們的構(gòu)造函數(shù),使用下面的主程序演示全局對象的情況:【例4.6】使用前面定義的Point類演示全局對象的例子。Pointglobal(5,7);voidmain(){cout<<"Enteringmainandexitingmain“<<endl;}程序在進入main函數(shù)之前先構(gòu)造全局對象,輸出“Initializing5,7”。進入主函數(shù)之后輸出為:Enteringmainandexitingmain。第35頁,共108頁,2023年,2月20日,星期四2.自動調(diào)用構(gòu)造類成員函數(shù)程序員不能在程序中顯式地調(diào)用構(gòu)造類成員函數(shù),這類函數(shù)是自動調(diào)用的。Pointa.Point(x,y);錯誤Pointa(x,y);。正確編譯系統(tǒng)會自動調(diào)用Point(x,y)產(chǎn)生對象a并使用x和y將其正確地初始化。也不能在產(chǎn)生對象a之后,使用構(gòu)造函數(shù)改變對象的屬性值。a.Point(x,y);錯誤如果要改變對象的屬性值,需要設(shè)計專門的成員函數(shù),如使用a.Setxy(x,y)改變對象的屬性值。第36頁,共108頁,2023年,2月20日,星期四4.2.3構(gòu)造函數(shù)和運算符new運算符new用于建立生存期可控的對象并返回這個對象的指針。使用new建立動態(tài)對象的語法和建立動態(tài)變量的情況類似,其不同點是new和構(gòu)造函數(shù)一同起作用。【例4.7】使用前面的Point類演示new運算符和構(gòu)造函數(shù)的關(guān)系的例子。voidmain(){Point*ptr1=newPoint;Point*ptr2=newPoint(5,7);deleteptr1;deleteptr2;}運行這個程序,程序的輸出結(jié)果是:InitializingdefaultInitializing5,7第37頁,共108頁,2023年,2月20日,星期四當使用new建立一個動態(tài)對象時,new首先分配足以保存Point類的一個對象所需要的內(nèi)存,然后自動調(diào)用構(gòu)造函數(shù)來初始化這塊內(nèi)存,再返回這個動態(tài)對象的地址。使用new建立的動態(tài)對象在不用時必須用delete刪除,以便釋放所占空間。第38頁,共108頁,2023年,2月20日,星期四4.2.4構(gòu)造函數(shù)的默認參數(shù)如果程序定義自己的有參數(shù)構(gòu)造函數(shù),又想使用無參數(shù)形式的構(gòu)造函數(shù),解決的方法是將相應(yīng)的構(gòu)造函數(shù)全部使用默認參數(shù)設(shè)計。

第39頁,共108頁,2023年,2月20日,星期四【例4.8】設(shè)計構(gòu)造函數(shù)的默認參數(shù)。#include<iostream>usingnamespacestd;classPoint{private:intx,y;public:Point(int=0,int=0);//聲明兩個參數(shù)均為默認參數(shù)};Point::Point(inta,intb):x(a),y(b)//定義構(gòu)造函數(shù){cout<<"Initializing"<<a<<","<<b<<endl;}第40頁,共108頁,2023年,2月20日,星期四voidmain(){PointA;//構(gòu)造函數(shù)產(chǎn)生對象APointB(15,25);//構(gòu)造函數(shù)產(chǎn)生對象BPointc[2];//構(gòu)造函數(shù)產(chǎn)生對象數(shù)組C}聲明構(gòu)造函數(shù)原型時不需要給出參數(shù)名,即使用“int=0,int=0”。程序輸出如下:Initializing0,0Initializing15,25Initializing0,0Initializing0,0第41頁,共108頁,2023年,2月20日,星期四4.2.5復(fù)制構(gòu)造函數(shù)引用在類中一個很重要的用途是用在復(fù)制構(gòu)造函數(shù)中。這是一類特殊而且重要的函數(shù),通常用于使用已有的對象來建立一個新對象。淺拷貝就是普通的數(shù)值復(fù)制。在通常情況下,編譯器建立一個默認復(fù)制構(gòu)造函數(shù),這個復(fù)制構(gòu)造函數(shù)采用淺拷貝來使用已有的對象來建立新對象,所以又直譯為拷貝構(gòu)造函數(shù)。第42頁,共108頁,2023年,2月20日,星期四對類A而言,復(fù)制(拷貝)構(gòu)造函數(shù)的原型為:

A::A(A&)首先它是一個構(gòu)造函數(shù)。其次,它的參數(shù)有些特別,是引用類自己的對象,即用一個已有的對象來創(chuàng)建一個新對象。為了不改變原有對象,更普通的形式是使用const限定: A::A(constA&)但如果存在指針時,是簡單地將兩個指針指向同一地址還是指向不同的存儲區(qū)域?簡單的賦值可能使兩個指針指向了同一塊存儲區(qū)域。當一個指針銷毀后,另外一個指針指向了無效區(qū)域,訪問這個指針可能會引起嚴重的錯誤。

第43頁,共108頁,2023年,2月20日,星期四為了克服這樣的缺點,需要自定義復(fù)制構(gòu)造函數(shù)。復(fù)制構(gòu)造函數(shù)的原型為:

Point(Point&);//復(fù)制構(gòu)造函數(shù)它的定義如下:

Point::Point(Point&t){x=t.x;y=t.y;}這個成員函數(shù)具有特殊的作用:在使用該類的一個對象初始化該類的另一個對象時,調(diào)用這個函數(shù)(有時又稱為復(fù)制初始化構(gòu)造函數(shù))。例如:

Pointobj1(25,52);

Pointobj2(obj1);//使用obj1的數(shù)據(jù)成員初始化obj2,//即數(shù)據(jù)成員為25和52為了安全起見,推薦使用的原型為:

Point(constPoint&)第44頁,共108頁,2023年,2月20日,星期四4.3析構(gòu)函數(shù)在對象消失時,使用析構(gòu)函數(shù)釋放由構(gòu)造函數(shù)分配的內(nèi)存。第45頁,共108頁,2023年,2月20日,星期四4.3.1定義析構(gòu)函數(shù)它也是一種特殊的成員函數(shù),執(zhí)行與構(gòu)造函數(shù)相反的操作,通常用于撤消對象時的一些清理任務(wù),如釋放分配給對象的內(nèi)存空間等。具有一些特殊的性質(zhì):與類名相同,但前面必須加一個波浪號(~);沒有參數(shù),也沒有返回值,而且不能重載。因此在一個類中只能有一個析構(gòu)函數(shù);當撤消對象時,編譯系統(tǒng)會自動地調(diào)用析構(gòu)函數(shù)。如果不顯式定義,系統(tǒng)自動生成一個空的析構(gòu)函數(shù)

第46頁,共108頁,2023年,2月20日,星期四例如:Point::~Point(){cout<<"Destructorisactive"<<endl;}使用下面的測試程序說明析構(gòu)函數(shù)的作用:voidmain(){PointA(5,68);cout<<"Exitingmain"<<endl;}執(zhí)行此程序,其輸出是:Initializing5,68//調(diào)用構(gòu)造函數(shù)Exitingmain//主程序輸出Destructorisactive//自動調(diào)用析構(gòu)函數(shù)當對象的生存期結(jié)束時,程序為這個對象調(diào)用析構(gòu)函數(shù),然后回收這個對象占用的內(nèi)存。全局對象和靜態(tài)對象的析構(gòu)函數(shù)在程序運行結(jié)束之前調(diào)用。全局對象數(shù)組和靜態(tài)對象數(shù)組的析構(gòu)函數(shù)在程序結(jié)束之前被調(diào)用。數(shù)組的每個元素調(diào)用一次析構(gòu)函數(shù)。第47頁,共108頁,2023年,2月20日,星期四4.3.2析構(gòu)函數(shù)和運算符delete運算符delete與析構(gòu)函數(shù)一起工作。當使用運算符delete刪除一個動態(tài)對象時,它首先為這個動態(tài)對象調(diào)用析構(gòu)函數(shù),然后再釋放這個動態(tài)對象占用的內(nèi)存,這和使用new建立動態(tài)對象的過程正好相反?!纠?.9】使用Point類演示建立和釋放一個動態(tài)對象數(shù)組的例子。#include<iostream>usingnamespacestd;classPoint{private:intx,y;

第48頁,共108頁,2023年,2月20日,星期四public:Point(int=0,int=0);//聲明兩個參數(shù)均為默認參數(shù)~Point();//聲明析構(gòu)函數(shù)};Point::Point(inta,intb):x(a),y(b)//定義構(gòu)造函數(shù){cout<<"Initializing"<<a<<","<<b<<endl;}Point::~Point()//定義析構(gòu)函數(shù){cout<<"Destructorisactive"<<endl;}voidmain(){ Point*ptr=newPoint[2]; delete[]ptr;}第49頁,共108頁,2023年,2月20日,星期四程序的輸出如下:Initializing0,0//調(diào)用構(gòu)造函數(shù)Initializing0,0//調(diào)用構(gòu)造函數(shù)Destructorisactive//調(diào)用析構(gòu)函數(shù)Destructorisactive//調(diào)用析構(gòu)函數(shù)C++使用“[]”號來說明這是動態(tài)對象數(shù)組即語句delete[]ptr;//注意不要錯為ptr[],而且[]號內(nèi)為空delete將為動態(tài)數(shù)組的每個對象調(diào)用一次析構(gòu)函數(shù),然后釋放ptr所指向的內(nèi)存。當程序先后創(chuàng)建幾個對象時,系統(tǒng)按后建先析構(gòu)的原則析構(gòu)對象。當使用delete調(diào)用析構(gòu)函數(shù)時,則按delete的順序析構(gòu)。第50頁,共108頁,2023年,2月20日,星期四4.3.3默認析構(gòu)函數(shù)如果在定義類時沒有定義析構(gòu)函數(shù),C++編譯器要為這個類產(chǎn)生一個默認的析構(gòu)函數(shù),正如沒有給類定義構(gòu)造函數(shù),C++編譯系統(tǒng)會產(chǎn)生一個默認構(gòu)造函數(shù)一樣,編譯器也為它產(chǎn)生一個函數(shù)體為空的默認析構(gòu)函數(shù):Test::~Test(){}第51頁,共108頁,2023年,2月20日,星期四4.4調(diào)用復(fù)制構(gòu)造函數(shù)的綜合實例

調(diào)用復(fù)制構(gòu)造函數(shù)的情況當用類的一個對象去初始化該類的另一個對象時,系統(tǒng)自動調(diào)用復(fù)制構(gòu)造函數(shù)實現(xiàn)拷貝賦值。Pointp2(p1);//用對象p1初始化對象p2,復(fù)制構(gòu)造函數(shù)被調(diào)用(代入法)Pointp3=p1;//用對象p1初始化對象p3,復(fù)制構(gòu)造函數(shù)被調(diào)用(賦值法)第52頁,共108頁,2023年,2月20日,星期四當函數(shù)的形參是類的對象,調(diào)用函數(shù),進行形參和實參結(jié)合時。voidfun1(Pointp){cout<<p.GetX()<<endl;}voidmain(){PointA(1,2);fun1(A);//調(diào)用復(fù)制構(gòu)造函數(shù)}當函數(shù)的返回值是對象,函數(shù)執(zhí)行完成,返回調(diào)用者時。Pointfun2(){PointA(1,2);returnA;//調(diào)用復(fù)制構(gòu)造函數(shù)}voidmain(){PointB;B=fun2();}第53頁,共108頁,2023年,2月20日,星期四【例4.10】演示調(diào)用構(gòu)造函數(shù)及析構(gòu)函數(shù)的綜合例子。#include<iostream>usingnamespacestd;classPoint{private: intX,Y;public: Point(inta=0,intb=0)//構(gòu)造函數(shù){X=a;Y=b;cout<<"Initializing"<<endl;}Point(constPoint&p);//復(fù)制構(gòu)造函數(shù)第54頁,共108頁,2023年,2月20日,星期四intGetX(){returnX;}intGetY(){returnY;}voidShow(){cout<<"X="<<X<<",Y="<<Y<<endl;}~Point(){cout<<"delete..."<<X<<","<<Y<<endl;}};Point::Point(constPoint&p)//定義復(fù)制構(gòu)造函數(shù){ X=p.X; Y=p.Y; cout<<"CopyInitializing"<<endl;}voiddisplay(Pointp)//Point類的對象作為函數(shù)的形參{p.Show();}voiddisp(Point&p)//Point類對象的引用作為函數(shù)的形參{p.Show();}第55頁,共108頁,2023年,2月20日,星期四Pointfun()//函數(shù)的返回值為Point類的對象{PointA(101,202);returnA;}voidmain(){PointA(42,35);//對象A//第1次調(diào)用復(fù)制構(gòu)造函數(shù)PointB(A); //①用A初始化BPointC(58,94);//對象Ccout<<"calleddisplay(B)"<<endl;//第2次調(diào)用復(fù)制構(gòu)造函數(shù)display(B); //②對象B作為display的實參

第56頁,共108頁,2023年,2月20日,星期四cout<<"Next..."<<endl;cout<<"calleddisp(B)"<<endl;disp(B);cout<<"callC=fun()"<<endl;//第3次調(diào)用復(fù)制構(gòu)造函數(shù)C=fun(); //③fun的返回值賦給對象Ccout<<"calleddisp(C)"<<endl;disp(C);cout<<"out..."<<endl;}第57頁,共108頁,2023年,2月20日,星期四輸出結(jié)果及注釋如下:Initializing//創(chuàng)建對象ACopyInitializing//調(diào)用復(fù)制構(gòu)造函數(shù),使用對象A初始化BInitializing//創(chuàng)建對象Ccalleddisplay(B)//用對象B作為參數(shù)CopyInitializing//需要調(diào)用復(fù)制構(gòu)造函數(shù)X=42,Y=35//進入函數(shù)體執(zhí)行語句delete...42,35//退出函數(shù)時,需要調(diào)用析構(gòu)函數(shù)清除對象Next...calleddisp(B)//使用引用做為參數(shù),則不需要//調(diào)用復(fù)制構(gòu)造函數(shù)X=42,Y=35//進入函數(shù)體執(zhí)行語句callC=fun()//C使用函數(shù)fun()的返回值Initializing//在函數(shù)fun()內(nèi)創(chuàng)建對象ACopyInitializing//調(diào)用復(fù)制構(gòu)造函數(shù)返回值第58頁,共108頁,2023年,2月20日,星期四delete...101,202//返回值給對象C,調(diào)用析構(gòu)函數(shù)//清除臨時對象delete...101,202//退出函數(shù)體,調(diào)用析構(gòu)函數(shù)清除//對象Acalleddisp(C)//使用引用做為參數(shù)X=101,Y=202//進入函數(shù)體執(zhí)行語句out...delete...101,202//調(diào)用析構(gòu)函數(shù)清除對象Cdelete...42,35//調(diào)用析構(gòu)函數(shù)清除對象Bdelete...42,35//調(diào)用析構(gòu)函數(shù)清除對象Adelete...101,202//將值傳給對象C,調(diào)用析構(gòu)函數(shù)//清除臨時對象delete...101,202//退出函數(shù)體,調(diào)用析構(gòu)函數(shù)//清除對象A第59頁,共108頁,2023年,2月20日,星期四第1句輸出比較簡單,調(diào)用函數(shù)fun,在其內(nèi)調(diào)用構(gòu)造函數(shù)Point(int,int)創(chuàng)建對象A。對象A的生命期與函數(shù)fun同在,結(jié)束調(diào)用時則調(diào)用析構(gòu)函數(shù)析構(gòu)對象A。在這個構(gòu)造與析構(gòu)之間,還有一個過程發(fā)生,即執(zhí)行“returnA;”時,目的是使得C=A,使C的數(shù)據(jù)成員與A的相同,但這要調(diào)用復(fù)制構(gòu)造函數(shù)實現(xiàn)。復(fù)制構(gòu)造函數(shù)是創(chuàng)建對象的,它產(chǎn)生一個臨時對象,用這個臨時對象完成C=A,然后再析構(gòu)這個臨時對象,這就是中間兩條輸出信息。這樣,語句“C=func();”就輸出如上4條信息。第60頁,共108頁,2023年,2月20日,星期四4.5成員函數(shù)重載及默認參數(shù)【例4.11】構(gòu)造一個求4個正整數(shù)中最大者的類Max,并用主程序驗證它的功能。classMax{//聲明類private://封裝數(shù)據(jù)成員和成員函數(shù)inta,b,c,d;//數(shù)據(jù)成員intMaxi(int,int);//只允許類內(nèi)部的成員函數(shù)調(diào)用public://對外界的接口voidSet(int,int,int,int);//設(shè)置對象初值intMaxi();//求最大值}A[3];//聲明類的對象數(shù)組,定義結(jié)束第61頁,共108頁,2023年,2月20日,星期四//類中成員函數(shù)的實現(xiàn)intMax::Maxi(intx,inty) //求二個數(shù)的最大值{return(x>y)?x:y;}//使用兩個默認參數(shù)voidMax::Set(intx1,intx2,intx3=0,intx4=0){a=x1;b=x2;c=x3;d=x4;}intMax::Maxi()//求自己類中四個數(shù)的最大值{ intx=Maxi(a,b);//x和y為Maxi()函數(shù)的局部整數(shù)對象inty=Maxi(c,d);returnMaxi(x,y);}第62頁,共108頁,2023年,2月20日,星期四//主程序#include<iostream>usingnamespacestd;voidmain(){ A[0].Set(12,45,76,89);//為數(shù)組對象A[0]置初值 A[1].Set(12,45,76);//為數(shù)組對象A[1]置初值 A[2].Set(12,45);//為數(shù)組對象A[2]置初值for(inti=0;i<3;i++)//輸出對象求值結(jié)果cout<<A[i].Maxi()<<"";}第63頁,共108頁,2023年,2月20日,星期四程序演示了可在聲明類的同時也聲明類的對象,這里是聲明對象數(shù)組A,作用與在主程序里使用“MaxA[3];”語句相同。為了提高可讀性,一般不在聲明類時聲明對象,這里只是為了演示它的性質(zhì)。程序輸出結(jié)果為:897645類中重載了函數(shù)Maxi,一個原型為Maxi(int,int),用來求兩數(shù)中的大者。因為它只被自己的成員函數(shù)使用,所以定義為private。另一個原型為Maxi(),它調(diào)用兩次Maxi(int,int),然后再用這兩次的結(jié)果作為Maxi(int,int)的參數(shù),求出4個數(shù)中的最大值。賦值成員函數(shù)Set使用2個默認參數(shù),是為了書寫方便。第64頁,共108頁,2023年,2月20日,星期四4.6this指針在定義Point類的兩個對象A和B之后,當執(zhí)行語句“A.Setxy(25,55);”時,A.x和A.y就被賦值。但是,函數(shù)Setxy(int,int)作為代碼,在計算機里是和具體的對象分開存儲的。那么,它是怎樣知道,是要對A進行操作而不是對B進行操作呢?當執(zhí)行A.Setxy(25,55)時,成員函數(shù)Setxy(int,int)有一個隱藏參數(shù),名為this指針。也就是說,源程序被編譯器編譯后,Setxy(inta,intb)實際上是如下形式:

voidPoint::Setxy(inta,intb,(Point*)this){this->x=a;this->y=b;}成員函數(shù)的this指針指向?qū)ο驛。成員中對x和y的引用表示是引用對象A的成員x和y。對于任何訪問該成員函數(shù)的類的對象來說,C++編譯器都認為是訪問this指針所指向的對象中的成員。第65頁,共108頁,2023年,2月20日,星期四C++規(guī)定,當一個成員函數(shù)被調(diào)用時,系統(tǒng)自動向它傳遞一個隱含的參數(shù),該參數(shù)是一個指向接受該函數(shù)調(diào)用的對象的指針,從而使成員函數(shù)知道該對哪個對象進行操作。在程序中,可以使用關(guān)鍵字this來引用該指針。使用this指針,保證了每個對象可以擁有自己的數(shù)據(jù)成員,但處理這些數(shù)據(jù)成員的代碼可以被所有的對象共享。除非特殊需要,一般情況下都省略符號“this->”,而讓系統(tǒng)進行默認設(shè)置。第66頁,共108頁,2023年,2月20日,星期四4.7一個類的對象作為另一個類的成員因為類本身就是一種新的數(shù)據(jù)類型,所以一個類可以作為另一個類的成員。假設(shè)有A和B兩個類,可以通過在B類里定義A的對象作為B的數(shù)據(jù)成員,或者定義一個返回類型為A的函數(shù)作為B的成員函數(shù)。第67頁,共108頁,2023年,2月20日,星期四假設(shè)定義了坐標點的類Point,矩形類Rectangle的屬性需要一個坐標點及長和寬。一個Point的對象恰好可以作為矩形的頂點坐標,即Rectangle可以使用Point的一個對象作為數(shù)據(jù)成員。在Rectangle類中,用Point類定義一個返回Point類型指針的函數(shù)作為Rectangle的成員函數(shù)。

【例4.12】使用對象成員的例子。#include<iostream>usingnamespacestd;classPoint{//定義點類 intx,y; public: voidSet(inta,intb){x=a;y=b;} intGetx(){returnx;} intGety(){returny;}};第68頁,共108頁,2023年,2月20日,星期四classRectangle{//在矩形類里使用Point類的成員PointLoc;//定義一個Point類的對象作為頂點intH,W;//H為高,W為寬public:voidSet(intx,inty,inth,intw);Point*GetLoc();//用Point類定義返回指針的函數(shù)intGetHeight(){returnH;}intGetWidth(){returnW;}};voidRectangle::Set(intx,inty,inth,intw){Loc.Set(x,y);//初始化坐標頂點H=h;W=w;}Point*Rectangle::GetLoc()//返回類型Point*,作//為Rectangle的成員函數(shù){return&Loc;}//返回對象Loc的地址第69頁,共108頁,2023年,2月20日,星期四voidmain(){Rectanglerect;rect.Set(10,2,25,20);cout<<rect.GetHeight()<<",“<<rect.GetWidth()<<",";Point*p=rect.GetLoc();//定義Point類的//指針對象p并初始化cout<<p->Getx()<<","<<p->Gety()<<endl;}新類Rectangle具有一個頂點,所以也具有Point類的屬性。這就是類的結(jié)構(gòu)關(guān)系(聚合關(guān)系,有時又稱包含)。構(gòu)成的新類不能直接操作另一個類的數(shù)據(jù),必須通過原構(gòu)成類的對象使用它們的成員函數(shù)來實現(xiàn),本例使用Loc.Set(x,y)方式實現(xiàn)。程序輸出結(jié)果為:25,20,10,2第70頁,共108頁,2023年,2月20日,星期四4.8類和對象的性質(zhì)4.8.1類對象的性質(zhì)歸納對象的一些基本特性如下:①對象之間可以相互賦值。例如,如下語句使A和B的數(shù)據(jù)成員有相同的值:PointA,B;A.Setxy(25,55);B=A;②可使用對象數(shù)組。例如,“MaxA[3];”定義數(shù)組A可以存儲3個Point類的對象。③可使用指向?qū)ο蟮闹羔?,使用取地址運算符&將一個對象的地址置于該指針中,如:Point*p=&A;p->Display();注意,不能取私有數(shù)據(jù)成員的地址,也不能取成員函數(shù)的地址。第71頁,共108頁,2023年,2月20日,星期四④對象可以用做函數(shù)參數(shù),這時參數(shù)傳遞可以采用傳值方式,也可以傳址,采用對象的引用或指針作為參數(shù)。但是,如參數(shù)對象被修改,相應(yīng)的實參對象也將被修改。C++推薦使用引用作為參數(shù)傳遞。為了避免被調(diào)用函數(shù)修改原來對象的數(shù)據(jù)成員,可以使用const修飾符。⑤對象作為函數(shù)參數(shù)時,可以使用對象值、對象引用和對象地址(指針)。以介紹過的print函數(shù)為例,它們的參數(shù)傳遞形式為:voidprint(Pointa){a.Display;}voidprint(Point&a){a.Display;}voidprint(Point*p){p->Display;}它們的原型分別print(Point);print(Point&);print(Point*);對于對象A,print(&A)調(diào)用的是原型為print(Point*)的函數(shù)形式。注意:參數(shù)為對象和引用時,編譯系統(tǒng)無法區(qū)別,重載print只能選擇其中的一種。⑥一個對象可以用做另一個對象的成員。例如定義Point類的對象Loc為Rectangle的數(shù)據(jù)成員,GetLoc()作為返回Point類型指針的函數(shù)。第72頁,共108頁,2023年,2月20日,星期四4.8.2類的性質(zhì)1.使用類的權(quán)限①類本身的成員函數(shù)可以使用類的所有成員(私有和公有成員)。②類的對象只能訪問公有成員函數(shù),例如輸出x只能使用A.Getx()不能使用A.x。③其他函數(shù)不能使用類的私有成員,也不能使用公有成員函數(shù),它們只能通過類的對象使用公有成員函數(shù)。④一個類可以使用另外一個類的對象,這個類也只能通過那個類的對象使用該類的成員函數(shù),通過成員函數(shù)使用數(shù)據(jù)成員,例如Loc.Set(x,y)。第73頁,共108頁,2023年,2月20日,星期四2.不完全的類聲明類不是內(nèi)存中的物理實體,只有當使用類產(chǎn)生對象時,才進行內(nèi)存分配,這種對象建立的過程稱為實例化。應(yīng)當注意的是:類必須在其成員被使用之前先進行聲明。然而,有時也需要將類作為一個整體來使用,而不存取其成員。聲明指針就是這種情況,例如:classMembersOnly;//不完全的類聲明MembersOnly*club;//定義一個全局變量類指針voidmain(){…//函數(shù)體}//主函數(shù)classMembersOnly{…//類體};//完全定義該類第74頁,共108頁,2023年,2月20日,星期四第一條語句稱為不完全類聲明,它用于在類沒有完全定義之前就引用該類的情況,可以聲明全局變量指針club。編譯器執(zhí)行到該指針的聲明處時,只了解指針所指類型是一個叫MembersOnly的類,而不了解其他任何情況。不完全聲明的類不能實例化,企圖實例化會產(chǎn)生編譯出錯信息;不完全聲明僅用于類和結(jié)構(gòu),企圖存取沒有完全聲明的類成員,也會引起編譯出錯信息。另外,將數(shù)據(jù)成員的聲明放在最后,有利于先理解類的界面。第75頁,共108頁,2023年,2月20日,星期四3.空類盡管類的目的是封裝代碼和數(shù)據(jù),它也可以不包括任何聲明。例如:classEmpty{};當然,這種類沒有任何行為,但可以產(chǎn)生空類對象。voidmain(){Emptyobject;}為什么要產(chǎn)生空類呢?在開發(fā)大的項目時,需要在一些類還沒有完全定義或?qū)崿F(xiàn)時進行先期測試。這常稱為“插頭”,用來保證代碼能正確地被編譯,從而允許測試其中的一部分。不過這是早期的做法,對強類型檢查的編譯器,會給出一個警告??山o空類增加一個無參數(shù)構(gòu)造函數(shù)(見構(gòu)造函數(shù)一節(jié))以消除警告。例如:classEmpty{public:Empty(){}};第76頁,共108頁,2023年,2月20日,星期四4.類作用域聲明類時所使用的一對花括號形成所謂的類作用域。在類作用域中聲明的標識符只在類中可見。例如:classexample{intnum;};inti=num;//錯,num在此不可見intnum;//正確,num與類中說明的數(shù)據(jù)//成員num具有不同的作用域第77頁,共108頁,2023年,2月20日,星期四即使該成員函數(shù)的實現(xiàn)是在類定義之外給出的,類作用域也包含了類中成員函數(shù)的作用域classMyClass{intnumber;public:voidset(int);};intnumber;//這個number不屬于類MyClassvoidMyClass::set(inti){number=i;//使用類MyClass中的標識符number}類中的一個成員名可以使用類名和作用域運算符來顯式指定,這稱為成員名限定。例如:voidMyClass::set(inti){MyClass::number=i;//顯式指定訪問MyClass//類中的標識符number}第78頁,共108頁,2023年,2月20日,星期四在程序中使用成員選擇運算符(“.”或“->”)訪問一個對象的成員時,其后的名字是引用該對象所在類中聲明的成員名。例如:PointA;//聲明類對象,假設(shè)類//內(nèi)有成員函數(shù)Getx()intGetx(){return5;};//類外面聲明的函數(shù)intx=Getx();//訪問函數(shù)Getx(),返回5inty=A.Getx();//訪問類Point中聲明的//成員函數(shù)Getx()第79頁,共108頁,2023年,2月20日,星期四除非編譯器在處理類聲明時遇到了標識其結(jié)束的右花括號,否則這個聲明仍然是引用性聲明。引用性聲明所聲明的類名不能用來建立對象,只能用來聲明指針或引用,或用在函數(shù)聲明中。例如:classMyClass{MyClassmember;//錯MyClass*p;//正確};classYourClass{private:MyClassd;//正確};當在類MyClass中聲明成員member時,類名MyClass僅作了引用性聲明,因而這個語句是錯誤的。第80頁,共108頁,2023年,2月20日,星期四4.9面向?qū)ο蟮臉擞泩D為了設(shè)計、開發(fā)和相互交流的需要,采用圖像形式將面向?qū)ο蟪绦蛟O(shè)計對問題的描述直觀地表示出來。UML是一種可視化建模語言,主要用于面向?qū)ο蠓治龊徒!1緯饕墙柚谒鼇碚f明類的有關(guān)知識。第81頁,共108頁,2023年,2月20日,星期四4.9.1類和對象的UML標記圖

類和對象的標記符號類似,它們都只能表示靜態(tài)特征。如圖4.1所示,在UML語言中,類使用短式和長式兩種方式表示。第82頁,共108頁,2023年,2月20日,星期四短式僅用1個含有類名的長方框表示。長式使用3個方框表示。最上面的框中填入類的名稱,中間框中填入屬性(C++中稱為數(shù)據(jù)成員),最下面的框中填入成員函數(shù)(操作)。屬性和操作可以根據(jù)需要進行細化。第83頁,共108頁,2023年,2月20日,星期四圖4.2對象的標記圖對象的表示有3種方式,最簡單的是只填寫對象名稱,完整的方式是給出對象名和類名(類名在右邊,兩者之間用冒號連接),并用下劃線將它們標注出來。當還沒有決定這個對象的名稱時,可以不給出對象名,但不能省去“:”號。第84頁,共108頁,2023年,2月20日,星期四4.9.2表示對象的結(jié)構(gòu)與連接只有定義和描述了對象類之間的關(guān)系,各個對象

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論