版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、.第12章 面向對象程序設計與C+基礎程序設計語言是編寫程序的工具,程序設計語言的發(fā)展反映了程序設計方法的演變過程。隨著計算機技術的日新月異,要求軟件具有良好的可重用性和可擴展性,這就導致程序設計方法從結構化程序設計方式轉變到面向對象程序設計方式。C語言能夠很好地支持結構化程序設計,C+不僅兼容C,同時具有面向對象的特征,因此充分支持面向對象程序設計。12.1 面向對象程序設計的基本概念面向對象技術變革了軟件設計的傳統(tǒng)方法。解決結構化程序設計不足的方法就是限制數(shù)據(jù)的存取權限,面向對象程序設計把數(shù)據(jù)和使用此數(shù)據(jù)的過程封裝成一個類(類可看成是一個基本數(shù)據(jù)類型)。數(shù)據(jù)的封裝和隱藏一方面使得內部數(shù)據(jù)不
2、被破壞,另一方面程序具有良好的可讀性和相對獨立性。類的繼承機制不僅提高了代碼的可重用性,降低了軟件開發(fā)難度和開發(fā)周期,同時程序的修改變得容易,軟件結構更加穩(wěn)定,軟件的可維護性大大提高。面向對象軟件系統(tǒng)由類的層次結構組成,類的具體實例叫做對象,對象之間通過彼此的聯(lián)系,共同實現(xiàn)程序的功能。如圖12-1所示。數(shù)據(jù)方法數(shù)據(jù)方法數(shù)據(jù)方法數(shù)據(jù)方法類的層次結構圖12-1 面向對象軟件系統(tǒng) 面向對象程序設計方法提出一些全新的概念:對象、類、封裝、數(shù)據(jù)隱藏、繼承和多態(tài)性等。多態(tài)性、數(shù)據(jù)封裝和繼承共同構筑了面向對象程序設計的三大機制。屬性:顏色、進水量、洗滌指示操作方法:進水 排水 洗滌 甩干圖12-2 洗衣機類
3、示意圖1. 類與對象面向對象的方法學認為,客觀世界由對象組成,對象有自己獨特的特征和行為,兩者密不可分。面向對象的軟件技術中,類是將不同類型的數(shù)據(jù)和與這些數(shù)據(jù)相關的操作封裝在一起的集合體。對象可看成類的具體實例。圖12-2描述了洗衣機類。【例12-1】 在現(xiàn)實世界中,鋼筆具有筆帽、筆體、筆尖、顏色、形狀等屬性特征,鋼筆具有的行為是書寫、灌鋼筆水。鋼筆作為一個整體,具有獨特的屬性和行為,它們將被抽象成一個鋼筆類。這種自成一體性稱為封裝性。而你正在使用的鋼筆,可以看成鋼筆類中的一個具體實例。我們不必關心鋼筆的內部結構及實現(xiàn)細節(jié),僅利用鋼筆對外提供的操作,即外部接口,就可以方便地使用鋼筆?!纠?2-
4、2】 對于整型類型的數(shù)據(jù),可以定義對它的四則運算,這是整型數(shù)據(jù)具有的行為,四則運算與整型數(shù)據(jù)封裝成一體,命名為“int類”。字符型運算和邏輯運算不可以訪問、修改int類中的數(shù)據(jù),只有int類中定義的四則運算才能對其進行操作。顯然,我們也無需知道四則運算是如何定義的,int類對外界提供的操作接口是“+”、“”、“*”、“/”,可以直接利用這些接口實現(xiàn)整數(shù)的四則運算,這叫做數(shù)據(jù)的隱藏性。2. 數(shù)據(jù)的封裝和隱藏封裝強調的是數(shù)據(jù)和行為的自成一體性,也就是將數(shù)據(jù)和操作數(shù)據(jù)的函數(shù)代碼進行有機的結合,形成“類”。封裝具有如下意義:1) 面向對象的程序表現(xiàn)出強烈的可讀性和獨立性。2) 程序不依賴數(shù)據(jù)結構的改變
5、,具有良好的可維護性。當數(shù)據(jù)結構改變時,只有類中對數(shù)據(jù)進行操作的函數(shù)需要修改,程序的其他部分不受影響。3) 對數(shù)據(jù)起到一定的保護作用。只有類中的函數(shù)才可以修改類中的私有數(shù)據(jù)。 隱藏是指類把對數(shù)據(jù)的操作信息隱藏在內部,只提供對象對外的操作接口,用戶只能看見對象封裝接口上的信息,這樣可以保護內部數(shù)據(jù)不被破壞,同時使用者使用起來非常方便,并可以容易地將其擴展成新的產(chǎn)品。3. 類的繼承類的繼承是指新的派生類可以繼承原有父類的全部數(shù)據(jù)和操作的機制,并可以在派生類中添加新的數(shù)據(jù)和操作方法。新的派生類又叫子類,原有父類又叫基類或超類。例如,想生產(chǎn)敞篷汽車不用從草圖開始,只需要對原有的產(chǎn)品添加新的敞篷功能,這
6、樣就會快速開發(fā)出一種新的產(chǎn)品。利用類的繼承特性,可以非常方便地產(chǎn)生一系列具有相似特征的對象。再看一個類繼承的例子。在小學,我們學過數(shù)的四則運算,到中學會進一步學到對數(shù)、指數(shù)等運算,到大學將學到微積分等內容。我們每一次的進步都將繼承已學過的知識,在已有的基礎上不斷擴充新的知識。 4. 消息對象之間通過消息相互聯(lián)系,也是通過消息讓某一個對象完成一定的功能。例如,給洗衣機對象發(fā)洗滌的操作信號,洗衣機就會執(zhí)行洗滌的功能。在面向對象的程序設計中,消息名就是在對象中定義的操作(或稱方法),給對象發(fā)消息,就是讓對象執(zhí)行某一操作,使對象具有行為的能力。如圖12-3所示。邊長、頂點求周長 求面積發(fā)消息求面積執(zhí)行
7、操作求面積在C+中的表示:A 求面積(邊長,頂點坐標)圖12-3 消息機制5. 多態(tài)性多態(tài)性表示同一種東西有多種形態(tài)。例如,與對方通信,這個動作將有多種表現(xiàn)形態(tài),如采用寫信的方式、打電話、發(fā)電報、發(fā)電子郵件等。在面向對象的程序設計中,多態(tài)性是指同一個(或相似的)操作作用于不同的對象上可以有不同的獨特行為,比如add操作,作用在實數(shù)對象上,表現(xiàn)為兩個實數(shù)相加,作用在虛數(shù)對象上,表現(xiàn)為兩個虛數(shù)相加。面向對象的C+語言允許程序員給不同的對象發(fā)同一消息,軟件系統(tǒng)會做出決策,即到底執(zhí)行什么動作。在靜態(tài)(編譯或連接)時就可以分辨的,可通過函數(shù)重載實現(xiàn);在運行時才能分辨的,可通過虛函數(shù)實現(xiàn)。利用多態(tài)性,用戶
8、能夠發(fā)送一般形式的消息,而將所有的實現(xiàn)細節(jié)留給接收消息的對象。這種高層次的抽象, 使得多態(tài)性、數(shù)據(jù)封裝和繼承共同構筑了面向對象程序設計的三大機制。12.2 面向對象程序設計語言C+簡介C語言是一種受到廣泛重視和應用的面向過程編程的語言,它采用結構化程序設計技術,即把復雜的模塊層層分解為一系列簡單模塊。人們側重于開發(fā)具有特定功能的函數(shù),而有些數(shù)據(jù)(特別是全局數(shù)據(jù))在函數(shù)間可隨意傳遞。結構化程序設計語言無法處理高度復雜的程序,為了彌補結構化C語言的不足,支持面向對象的程序設計的C+語言應運而生。C+語言是一種混合性語言,保留了C語言的全部內容,同時擴展了C語言所不具有的面向對象編程的機制。C+在技
9、術上與C完全兼容,但它具有與C語言完全不同的思維方式,即支持面向對象的程序設計思想,強調對數(shù)據(jù)進行封裝、保護等深入的維護,強調軟件的可擴展性、可修改性和可維護性。利用C+語言可以進行結構化編程, 更重要的功能是進行面向對象的編程。12.2.1 C+程序結構本小節(jié)主要介紹兩個程序, 一個是面向過程的C+程序,見例12-3; 一個是面向對象的C+程序,見例12-4。通過這兩個實例,讀者可以對C+程序結構有個初步認識?!纠?2-3】 以下程序實現(xiàn)輸入一個整數(shù),求平方根并打印出來。/ 程序名: csqrt.cpp#include /定義cout()、cin()的頭文件#include /定義sqrt(
10、)的頭文件using namespace std; /使用命名空間stdvoid main() int x; coutx; /從鍵盤接收數(shù)據(jù)存入變量x中coutthe squart of number=sqrt(x)endl;/輸出數(shù)據(jù)程序運行情況:input number4the squart of number=2說明:1) C+程序注釋行以“/”開頭,也可以使用C語言的注釋行方式。2) C+程序的后綴通常為cpp。3) cout、cin是C+語言中增加的用來輸出和輸入的函數(shù),分別代表標準的輸出設備對象和輸入設備對象。這兩個C+函數(shù)是在輸入輸出流頭文件iostream內定義的。cout的使
11、用形式:cout變量。4) endl 操作符表示以后的輸出換行打印。 5)C標準程序庫中的所有標識符都被定義于一個名為std的namespace中,程序中第4行的使用,使得命名空間std內定義的所有C+標準庫函數(shù)名和標識符都有效,就好像它們被聲明為全局變量一樣。面向對象程序設計的首要任務是設計類,自頂向下利用演繹的思想,由抽象類派生具體的子類;自底向上利用歸納的思想,由具體的子類歸納出具有共同特征的抽象的父類,從而建立類的層次結構。再以類為模板創(chuàng)建不同的對象,然后協(xié)調這些對象共同工作。程序的運行從main函數(shù)開始?!纠?2-4】 編寫一個簡單的面向對象的C+程序:設計一個sample類, 對整
12、型數(shù)據(jù)進行管理, 初始化并顯示對象。1: #include2: using namespace std; 3:class sample / create a class4: 5: private:6: int i;7: public:8: void initial();9: void display(); 10: ; 11: void sample: initial()/定義類的初始化成員函數(shù)12: i = 0; 13 14: void sample: display()/定義類的顯示成員函數(shù)15: cout i endl; 16 17: void main() 18: sample A;/定
13、義類sample 的對象A19: A.initial();/給對象A 發(fā)消息, 進行對象的初始化20: cout Object A ,i = ;21: A.display();/給對象A 發(fā)消息, 顯示對象22: 運行結果:Object A ,i = 0說明:程序的第310行,用來聲明類sample。其中class是C+用來聲明類的關鍵字。該類中定義了私有的整型數(shù)據(jù)成員i,以及公有成員函數(shù)initial()和display()。私有的整型數(shù)據(jù)成員i只能通過兩個公有成員函數(shù)進行初始化和顯示。 程序的第1113行,用來定義類的公有成員函數(shù)initial() ,其作用是初始化對象。程序的第1416行
14、,用來定義類的公有成員函數(shù)display() ,其作用是顯示對象。程序的第1722行,是主函數(shù),其中第18行用來定義一個具體的對象A,這意味著在內存為對象A分配空間,如圖12-4所示。第19行是給對象A發(fā)初始化的消息,對象A執(zhí)行initial()函數(shù),改變對象A的狀態(tài),如圖12-5所示。第21行是給對象A發(fā)顯示的消息,對象A執(zhí)行display()函數(shù),顯示對象A的狀態(tài)。 對象Ai圖12-5對象A初始化 0對象Ai圖12-4 定義類的對象A12.2.2 C+對C的補充1. 注釋行C+的注釋有兩種類型:一種是沿用C語言的方法,采用“/*”和“*/”括起來進行注釋,另一種方法是只能用于C+的單行注釋
15、,即從“/”開始,直到所在行的行尾,所有字符都被作為注釋處理。2. C+的cin與coutcout、cin是C+語言中增加的用來輸出和輸入的函數(shù),分別代表輸出設備對象和輸入設備對象。cout和cin函數(shù)的使用方式不隨變量的類型變化,這正是面向對象語言所追求的。cout是代表標準輸出的流設備,如顯示屏。輸出操作必須配合操作符“”,表示把該操作符右邊的數(shù)據(jù)輸出到顯示屏上。cin是代表標準輸入的流設備,如輸入設備鍵盤。輸入操作必須配合操作符“”,代表從標準輸入設備讀取數(shù)據(jù)到內存。 cin與cout 定義在輸入輸出流頭文件iostream.h中。3. 關鍵字const定義符號常量C+中的符號常量使用關
16、鍵字const來說明,其一般形式:const 類型說明符 常量名=常量值或類型說明符const 常量名=常量值例如:定義一個buf的常量。const int buf=512或int const buf=5124. new和delete運算符C+新增new和delete作為動態(tài)內存分配和釋放的操作符,用來增強C語言中原有的函數(shù)malloc和free,提高了內存管理的靈活性。例如:int *p; /定義指向整數(shù)的指針變量p=new int;/動態(tài)申請存放整數(shù)的內存空間delete p; /釋放p指向的動態(tài)內存空間5. 引用作為函數(shù)參數(shù)C+新增了引用,它使函數(shù)調用變得清晰、簡單,參數(shù)傳遞效率更高。同
17、時,將引用作為函數(shù)參數(shù)給編程帶來了很大的靈活性。引用可看成某個目標變量的別名,對引用的操作,實際上就是對目標變量的操作,引用與目標變量完全對應。一旦用目標變量給引用賦初值,引用就被維系在該目標變量上,即引用不會再與其他目標變量建立聯(lián)系。引用不能是空,與此相反,指針變量可以為空。聲明并初始化引用的一般格式:數(shù)據(jù)類型& 引用名=目標變量;其中,“數(shù)據(jù)類型”是定義目標變量的類型,而“數(shù)據(jù)類型&”是用來聲明引用的。例如:int m;int& kk=m; /聲明kk是對整型變量m的引用m=4;kk=10;/此時目標變量m的值通過引用改為10【例12-5】 引用作為函數(shù)參數(shù)。#include using
18、namespace std;void swap(int&, int&);/聲明形參是引用類型void main() int x=10, y=20; coutbefore swap, x=x, y=yendl; swap(x,y);/函數(shù)調用,實際傳遞的是實參地址 coutafter swap, x=x, y=yendl;void swap(int& xx, int& yy)/形參是引用類型 int temp; temp=xx; xx=yy; yy=temp;運行結果:before swap, x=10, y=20after swap, x=20, y=10該程序通過調用函數(shù)swap(),交換主
19、函數(shù)中變量x和y的值。在主函數(shù)中,調用函數(shù)swap(x,y)時,實參看起來是值傳遞,其實傳遞的是實參地址。在定義函數(shù)swap()時,形參是引用類型,這就使得引用xx與目標實參x的地址維系在一起,引用yy與目標實參y的地址維系在一起。在執(zhí)行函數(shù)swap()時,對引用xx與yy的操作,實際上就是對x與y的操作?!纠?2-6】 指針作為參數(shù)實現(xiàn)與上述程序同樣的功能。#include using namespace std;void swap( int *, int * );/聲明形參是指針類型void main() int x=10, y=20; coutbefore swap, x=x, y=ye
20、ndl; swap(&x, &y);/函數(shù)調用,傳遞實參的地址 coutafter swap, x=x, y=yendl;void swap(int * xx, int * yy)/形參是指針類型 int temp; temp=*xx; *xx=*yy; *yy=temp;運行結果:before swap, x=10, y=20after swap, x=20, y=10該程序在調用函數(shù)swap()時,實參是&x與&y, 表明將把x與y的地址傳入到形參中, 而形參必須聲明為指針類型,接收傳進來的地址。在函數(shù)swap()的定義體中,*xx是指針變量xx所指向的變量,實際上就是主函數(shù)中的變量x;*
21、yy是指針變量yy所指向的變量,實際上就是主函數(shù)中的變量y。通過上述兩個程序風格的對比,形參是引用時,函數(shù)體簡練、清晰、可讀性好。而形參是指針類型時,函數(shù)體內過多的指針運算降低了程序的可讀性,容易產(chǎn)生錯誤。當形參是引用時,傳遞的是實參本身(通過傳遞地址的形式),因此當函數(shù)被調用時,在函數(shù)作用域內, 并沒有建立實參的副本,這種機制大大提高了效率,節(jié)省了空間。比如,若要傳遞的參數(shù)是結構或類這樣較大的數(shù)據(jù)類型,顯然不希望復制副本,以提高參數(shù)傳遞的效率,并節(jié)省內存。當形參既不是引用也不是指針變量時,參數(shù)傳遞屬于值傳遞,此時若函數(shù)被調用,必須在函數(shù)作用域建立實參的副本,這通常以時間和空間的浪費為代價。
22、6. 函數(shù)返回類型是引用當函數(shù)返回類型不是引用時,實際上是在內存中開辟臨時空間存放函數(shù)返回的值,而函數(shù)返回類型是引用時,不需要這樣一個中間過程,即不需要產(chǎn)生臨時變量以存放返回值,而直接把返回值傳回到主函數(shù)中,從而大大提高程序執(zhí)行的效率,同樣也節(jié)省了空間。注意 不要返回不在主函數(shù)作用域內的變量或對象的引用?!纠?2-7】 返回引用類型的應用。#include using namespace std;int large;int& max(x,y) large=(xy)?x:y; return large; /返回變量large的引用void main() int d=max(10,46);/返回變
23、量large的引用,使得large的值直接傳給d int& f=max(10,56);/引用f與目標large維系在一起7. 內聯(lián)函數(shù) 為了減少函數(shù)調用的開銷,C+引入了內聯(lián)函數(shù)。 內聯(lián)函數(shù)的功能是強迫C+編譯程序直接使用函數(shù)體代碼替換調用語句,以提高程序的運行速度。內聯(lián)函數(shù)定義的一般形式:inline 函數(shù)類型 函數(shù)名(形參表) 函數(shù)體 如果在類的聲明中直接給出成員函數(shù)的定義,該成員函數(shù)默認為內聯(lián)函數(shù)。通常只將規(guī)模較小又使用頻繁的函數(shù)設計為內聯(lián)函數(shù)。8. 帶默認形參值的函數(shù)C+允許定義帶多個默認形參值的函數(shù)。例如,設函數(shù)原型聲明情況如下:int change(int x=10, int y=
24、20);則函數(shù)調用情況如下:change(40); / 形參y采用默認值20change(); / 形參x和y都采用默認值12.2.3 C+中的類1. 類的定義類是由成員組成的,包括一組數(shù)據(jù)成員和成員函數(shù),其定義的一般形式:class 類名 private: 私有數(shù)據(jù)和成員函數(shù) public: 公有數(shù)據(jù)和成員函數(shù) protected: 保護數(shù)據(jù)和成員函數(shù) ;類的名稱由關鍵字class開始,類的定義體夾在一對花括號中,后面可以跟分號,或一組屬于該類的對象。類內的一組成員變量和成員函數(shù)可以有以下三種類型:私有數(shù)據(jù)類型(private)、保護數(shù)據(jù)類型(protected)、公有數(shù)據(jù)類型(public
25、)。如果用private來說明類的數(shù)據(jù)和成員函數(shù),則意味著它們只能被該類中定義的成員函數(shù)和友元函數(shù)訪問。通常數(shù)據(jù)默認為私有類型,私有類型的保留字private可以省略。如果用protected來說明類的數(shù)據(jù)和成員函數(shù),則意味著它們只能被該類中的成員函數(shù)、友元函數(shù)、該類的派生類中的成員函數(shù)所訪問。如果用public來說明類的數(shù)據(jù)和成員函數(shù),意味著可以在類的外部(不通過類的成員函數(shù),如主函數(shù))存取數(shù)據(jù)。類中的公有成員函數(shù)提供了該類對外的接口,即通過公有成員函數(shù),才可以訪問類的私有數(shù)據(jù)。2. 類的成員類的數(shù)據(jù)成員不僅包含普通的數(shù)據(jù)變量,而且還可以包含其他類的對象。類是一種新的數(shù)據(jù)類型,而對象可看成是
26、由類定義的變量。類的成員函數(shù)對類內的數(shù)據(jù)成員施加操作,實現(xiàn)類的特定功能。若成員函數(shù)很小,可以在類內定義,反之,一般在類外定義。數(shù)據(jù)成員通常定義為私有或保護類型,以便隱藏和保護數(shù)據(jù)。成員函數(shù)通常定義為公有類型,目的是提供對外的接口,以便能夠對類訪問。為了在類外定義成員函數(shù),必須指出該成員函數(shù)是屬于哪個類的,C+中引入了一個符號“:”,稱為作用域運算符。在類外定義成員函數(shù)的一般形式:函數(shù)返回類型 類名:成員函數(shù)名(形參表) 函數(shù)體 3. 對象的定義類是對具有相同屬性和行為的一組相似對象的抽象,而對象是類的具體實例。類可看成是一個抽象的數(shù)據(jù)類型,而類的對象就是屬于類的一個具體變量。類不是一個占有內存
27、的實體,但對象卻是。創(chuàng)建類中的對象,就是在內存中創(chuàng)建具體的對象,其含義就是在內存中為類中的數(shù)據(jù)分配存儲空間,它們是對象的具體體現(xiàn)。通常在子函數(shù)中、主函數(shù)中以及函數(shù)的前面采用如下方式定義對象:類名 對象名;這種方式使得對象如普通變量一樣,具有一定的作用域(生存期)。 4. 類成員的使用類中的成員,包括數(shù)據(jù)成員和成員函數(shù)。有了對象,若想使用類中的公有成員,可采用以下形式:對象名. 公有數(shù)據(jù)成員對象名. 公有成員函數(shù)例如,m.input(); 是指給對象m發(fā)消息input(),對象m執(zhí)行input()函數(shù)。 注意 類中的私有數(shù)據(jù)只能通過該類的成員函數(shù)進行訪問,類中的保護數(shù)據(jù)可被該類的成員函數(shù)以及該類
28、的派生類的成員函數(shù)或友元函數(shù)所訪問。5. 類成員的初始化(1) 數(shù)據(jù)成員初始化類中公有數(shù)據(jù)成員可像普通變量一樣使用,可在定義對象后,在需要時賦初值。假設有一公有數(shù)據(jù)num,對象名為A,則用如下方式初始化:A.num=10; / 公有數(shù)據(jù)可以直接使用類中的私有或保護數(shù)據(jù)只能在類及派生類中的成員函數(shù)或友元函數(shù)中使用,所以不允許直接引用類的實例對象中的私有或保護數(shù)據(jù)成員。如例12-6中,類 sample的實例對象為A,由于類sample中的i是私有數(shù)據(jù)成員,所以不可以采用如下方式賦值:A.i=5; / 錯誤, 私有數(shù)據(jù)不可以直接引用對私有數(shù)據(jù)i的初始化是通過類 sample中的初始化成員函數(shù)實現(xiàn)的。
29、(2) 對象的初始化對私有或保護數(shù)據(jù)成員的初始化可通過對象的初始化實現(xiàn)。對象的初始化就是給對象數(shù)據(jù)賦初值。對象的初始化一般有兩種方式:一是通過類中的普通成員函數(shù),二是通過類中的特殊成員函數(shù)。而最通用的是通過類中的特殊成員函數(shù),即構造函數(shù)來實現(xiàn)。在12.2.4節(jié)例12-10的主函數(shù)中,首先定義類DATE的實例對象m,以便給對象數(shù)據(jù)分配存儲單元(參看圖12-10),由于構造函數(shù)的特殊性,它可以在定義類中的對象的同時,由系統(tǒng)自動調用,初始化對象的數(shù)據(jù)。普通的初始化成員函數(shù),可用下面的方式初始化類的對象:A.initial(); /參看12.2.1節(jié)例12-6此時對象A調用成員函數(shù)initial()響
30、應消息,該函數(shù)給對象A的私有數(shù)據(jù)賦初值。12.2.4 C+中的構造函數(shù)和析構函數(shù) 1. 構造函數(shù)在C+中通常自動初始化對象的數(shù)據(jù)。為了做到這一點,可以定義一個特殊的成員函數(shù),它的名字與類名相同,稱為構造函數(shù)。構造函數(shù)的作用是在對象被創(chuàng)建時使用特定的值構造對象,或者說將對象初始化為一個特定的狀態(tài)。當我們定義屬于類的對象時,系統(tǒng)就自動執(zhí)行構造函數(shù),初始化具體的對象。如果程序沒有聲明構造函數(shù),系統(tǒng)會自動地為程序設置一個,此構造函數(shù)什么也不做。對象在創(chuàng)建時只是被分配空間,具體的初值只能由用戶定義的初始化函數(shù)來實現(xiàn)。關于構造函數(shù),給出以下幾點說明:1) 構造函數(shù)與類名相同。2) 構造函數(shù)沒有返回類型,也
31、不能是void類型。3) 構造函數(shù)不能被隨意調用,由系統(tǒng)自動調用。4) 構造函數(shù)可以重載,可以帶默認形參,可以是內聯(lián)函數(shù)。5) 構造函數(shù)可以帶參數(shù)也可不帶參數(shù),不帶參數(shù)的構造函數(shù)稱為默認的構造函數(shù)。2. 析構函數(shù)此外,C+還提供了一種特殊的成員函數(shù),叫做析構函數(shù)。當對象被取消時,系統(tǒng)首先會自動調用類的析構函數(shù),然后撤銷對象(釋放對象所占用的存儲空間)。如果程序中沒有聲明析構函數(shù),則系統(tǒng)會自動為程序設置一個析構函數(shù)。如果用new()函數(shù)動態(tài)分配對象,當動態(tài)對象被取消時,系統(tǒng)會調用析構函數(shù)。因此,通常在析構函數(shù)中設置delete()函數(shù)就會自動撤銷動態(tài)對象。關于析構函數(shù),給出以下幾點說明:1) 析
32、構函數(shù)的名稱與類名相同,但前面加符號“”。2) 析構函數(shù)沒有返回類型,也不能是void類型,沒有參數(shù)。3) 析構函數(shù)由系統(tǒng)自動調用,不能隨意調用,不能重載。4) 一個類中只能有一個析構函數(shù)。5) 基類的析構函數(shù)可以是虛函數(shù),以便系統(tǒng)調用派生類析構函數(shù),撤銷其對象?!纠?2-8】 編寫一個日期類DATE,對年、月、日進行管理,能響應詢問日期及判斷是否閏年。#include using namespace std;class DATE/定義DATE類int year;/定義類的私有數(shù)據(jù), private可省略 int month;int day;public:DATE()/定義類的構造成員函數(shù),
33、初始化對象 year=month=day=0;int leapyear()/定義判斷閏年的成員函數(shù) if(year%4=0 & year %100 !=0) | year%400=0) return 1; else return 0; void input()/定義輸入數(shù)據(jù)的成員函數(shù),并對輸入的數(shù)據(jù)進行分析判斷 int days=31,28,31,30,31,30,30,31,30,31,30,31; int cc; while(1) cout year month day; if(month = 1 & month 0 & day =cc) break; void disp()/定義顯示數(shù)據(jù)
34、的成員函數(shù) cout Y= year M= month D= day endl;/類聲明結束void main()/定義主函數(shù), 實現(xiàn)類的實例化,并給對象發(fā)消息 DATE m;/定義對象m, 系統(tǒng)自動調用構造函數(shù)初始化對象 m.input();/給對象m發(fā)消息input, 使對象的數(shù)據(jù)發(fā)生變化 if(m.leapyear()/給對象發(fā)消息, 判斷是否閏年 cout Leap year!; else cout Not leap year!; m.disp();/給對象發(fā)消息, 顯示日期程序運行情況:yearmonthday對象A圖12-6 實例化類中的對象Input Year Month Day
35、: 2006 11 8Not leap year! Y=2006 M=11 D=8說明:當在主函數(shù)中定義對象m后,具體的對象就存在了,如圖12-6所示。由于C+系統(tǒng)可以在定義對象時自動調用構造函數(shù)初始化,所以一開始對象m的數(shù)據(jù)被初始化為0?!纠?2-9】 帶有參數(shù)的構造函數(shù),以及析構函數(shù)程序。#include using namespace std;class Example int i;public: Example( int x);/帶參數(shù)的構造函數(shù) Example()i=0;/不帶參數(shù)的默認的構造函數(shù) void display(); Example() coutDestroyed!end
36、l;/析構函數(shù);Example:Example(int x) i=x; void Example:display() coutI=iendl;void main() Example A(7);/定義對象A, 系統(tǒng)自動調用帶參數(shù)的構造函數(shù) Example B;/定義對象B, 系統(tǒng)自動調用默認的構造函數(shù) A.display(); B.display();運行結果:I=7I=0Destroyed!Destroyed!12.2.5 C+中的繼承繼承是C+語言的一種重要機制,該機制實現(xiàn)了對原有類進行擴充,在此基礎上進行更具體、更詳細的定義。通過繼承,新的派生類不僅可以自動獲得基類的所有成員變量和成員函數(shù)
37、(構造函數(shù)和私有函數(shù)除外),同時可定義新的成員變量和成員函數(shù),來滿足新的軟件需求,進一步完善程序設計,提高軟件的重用性。1. 派生類在C+中,派生類從一個基類繼承的一般形式:class 派生類名:public 基類名 成員變量和成員函數(shù)聲明; 其中,派生類名是新類名,public是最常用的繼承方式,本章主要介紹public繼承方式。此外,還有private、protected繼承方式,其特殊性可參考其他C+教材。注意 1) 自動從基類繼承下來的所有成員變量和成員函數(shù)不在派生類的定義中出現(xiàn),但若需要在派生類中重新定義基類的成員函數(shù),就必須在派生類的聲明中列出來,并為其賦予一個新定義,這如同在派生
38、類中新增一個成員函數(shù)。2) 任何其他類(包括派生類)的成員函數(shù)定義中,不能直接根據(jù)名稱訪問繼承下來的基類私有成員變量,但可以使用基類中定義的成員函數(shù)間接訪問基類的私有成員變量。3) 私有成員函數(shù)根本不會被繼承?!纠?2-10】 派生類程序示例(基類是例12-8中定義的DATE類)。/ 定義派生類Holidayclass Holiday: public DATE char name20;/派生類新增加的私有成員變量public: void set_name()/派生類新增成員函數(shù) coutEnter Name of Holiday:; cin.getline(name,80,n);/cin類中輸
39、入字符串函數(shù) void input()/更新來自基類的成員函數(shù) coutEnter Date of Holidayendl; DATE:input();/利用作用域調用基類的同名函數(shù) void disp()/更新來自基類的成員函數(shù) DATE:disp(); cout is name endl; ;/ 定義主函數(shù)void main()/實現(xiàn)派生類的實例化,并給對象發(fā)消息 Holiday H;/定義派生類對象H H.set_name();/給對象H發(fā)消息 H.input() ; if(H.leapyear()/leapyear()是繼承下來的公有成員函數(shù) cout Leap year!; else
40、 cout Not leap year!; H.disp() ; 程序運行情況:Enter Name of Holiday: May DayEnter Date of HolidayInput Year Month Day: 2000 5 1Leap year!Y=2000 M=5 D=1year, month, daynameset_name()input()disp()leapyear()圖12-7 派生類對象實體is May Day說明:派生類對象繼承下來基類的私有數(shù)據(jù)成員變量year, month, day,并添加新的數(shù)據(jù)成員變量name。派生類繼承基類的公有成員函數(shù)leapyear(
41、)(其代碼可重用,不需要重寫),并重新定義基類的公有成員函數(shù)disp()和input(),相當于新添加成員函數(shù)。另外,添加新的公有成員函數(shù)set_name()。如圖12-7所示。2. 基類的protected 成員不能在派生類的定義或實現(xiàn)中直接用名稱訪問基類的私有成員變量。但如果在基類中把成員變量和成員函數(shù)標記為protected性質,則在其派生類(以及派生類的派生類)中不僅能繼承下來,且可以用名稱直接訪問,其性質保持為protected。而在其他任何類或函數(shù)中,等同于用private來標記。12.2.6 C+中的多態(tài)性、函數(shù)重載和虛函數(shù)多態(tài)性是面向對象程序設計的重要特征之一。繼承重點研究類與
42、類的層次,多態(tài)則研究在不同層次的類中,同名成員函數(shù)的關系。所謂多態(tài)性就是同樣的接口有不同的功能,同樣的消息被不同的對象接收時產(chǎn)生不同的行為。C+獲得多態(tài)性的方式是函數(shù)重載、運算符重載和利用虛函數(shù)來實現(xiàn)。1. 函數(shù)重載普通函數(shù)、類的成員函數(shù)和友元函數(shù)都可以重載。函數(shù)重載是指函數(shù)名相同,但參數(shù)的類型和數(shù)量可以不同。系統(tǒng)根據(jù)其參數(shù)個數(shù)、參數(shù)類型,調用相應的函數(shù),執(zhí)行特定的功能。函數(shù)重載的意義在于能使用戶為某類操作起一個通用的名字,由編譯器在編譯時來確定選擇哪個函數(shù)來執(zhí)行某一操作,從而降低了程序的復雜性?!纠?2-11】 編寫兩個函數(shù),分別求整型數(shù)和浮點型數(shù)的最大值。#include using na
43、mespace std;int max(int a,int b);double max(double a, double b);int max(int a, int b) return (ab? a:b);double max(double a, double b) return (ab? a:b);void main() coutmax(2,5) max(3.5,6.7)endl;運行結果:5 6.72. 虛函數(shù)與純虛函數(shù)虛函數(shù)可以使程序在運行過程中動態(tài)地確定操作所針對的具體對象,從而實現(xiàn)運行時的多態(tài)性。聲明虛函數(shù)的方法是在基類中的成員函數(shù)原型前加上virtual。虛函數(shù)可以在一個或多個派生
44、類中重復定義,但要求必須與基類中的函數(shù)原型完全相同。這時,無論在派生類的相應成員函數(shù)前是否加上關鍵字virtual,都將視其為虛函數(shù)。在實際應用中,通常把基類中的虛函數(shù)定義為純虛函數(shù),即只在基類中聲明虛函數(shù),而不定義其函數(shù)體,將它的具體定義放到各個派生類中。通過該基類指針或引用,就可以在運行時調用所有派生類的虛函數(shù)。純虛函數(shù)的聲明的語法形式如下:virtual 函數(shù)類型 函數(shù)名(形參表)=0;【例12-12】 設計一個圖形類,利用純虛函數(shù)實現(xiàn)運行時的多態(tài)性。要求:計算矩形和三角形的面積。分析:首先定義一個抽象的圖形類Shape,在類Shape下可以派生出多種具體的形狀。為了求這些圖形的面積,只
45、需在類Shape中聲明一個純虛函數(shù)getArea(),而將計算具體形狀面積的定義放在其派生類中。#include using namespace std;class Shape protected: double x,y; public: void set(double a, double b) x=a; y=b; virtual void getArea()=0;class Triangle:public Shapepublic: void getArea() coutTriangle S=1/2*x*y=0.5*x*yendl;class Rectangle:public Shapepub
46、lic:void getArea() coutRectangle S=x*y= x*y set(3.4,6.7);/給對象t賦值p-getArea();/此時p-getArea()就調用Triangle的函數(shù)getArea()p=&r; /p指向Rectangle對象rp-set(3.4,6.7);/給對象r賦值p-getArea();/此時p-getArea()就調用Rectangle的函數(shù)getArea()運行結果:Triangle S=1/2*3.4*6.7=11.39Rectangle S=3.4*6.7=22.78小結C語言能夠很好地支持結構化程序設計,C+不僅兼容C,同時具有面向對象的特征,因此充分支持面向對象程序設計。結構化程序設計解決問題時,常常把復雜的問題分解為一系列數(shù)據(jù)和對數(shù)據(jù)進行處理的過程(或函數(shù)),因為數(shù)據(jù)沒有被“隱藏”在對它進行處理的過程中,這導致結構化程序設計存在著巨大的隱患。面向對象技術變革了軟件設計的傳統(tǒng)方法。面向對象程序設計把數(shù)據(jù)和使用此數(shù)據(jù)的過程封裝成一個類。數(shù)據(jù)的封裝和隱藏一方面使得內部數(shù)據(jù)不被破壞,另一方面使程序具有良
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經(jīng)權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年度廁所革命項目廁所革命標準制定與實施合同3篇
- 2025年度智能溫室大棚建筑與物聯(lián)網(wǎng)技術合同4篇
- 2025年度臨時用電安全設施更新改造協(xié)議4篇
- 2025年度美團外賣商家客戶關系管理系統(tǒng)協(xié)議4篇
- 2025年建筑材料綠色生產(chǎn)技術研發(fā)與應用合同3篇
- 2025年鴨苗養(yǎng)殖與冷鏈物流銷售合同規(guī)范3篇
- IT行業(yè)專屬保密合同書樣本下載版B版
- 科技前沿西安創(chuàng)新企業(yè)概覽
- 個人車輛租賃(2024版)
- 孕婦職場活力秘訣工作與健康雙豐收
- 高校鑄牢中華民族共同體意識教育的路徑研究
- 《面神經(jīng)炎護理措施分析》3900字(論文)
- 城市微電網(wǎng)建設實施方案
- 企業(yè)文化融入中華傳統(tǒng)文化的實施方案
- 9.1增強安全意識 教學設計 2024-2025學年統(tǒng)編版道德與法治七年級上冊
- 《化工設備機械基礎(第8版)》全套教學課件
- 人教版八年級數(shù)學下冊舉一反三專題17.6勾股定理章末八大題型總結(培優(yōu)篇)(學生版+解析)
- 2024屆上海高考語文課內古詩文背誦默寫篇目(精校版)
- DL-T5024-2020電力工程地基處理技術規(guī)程
- 初中數(shù)學要背誦記憶知識點(概念+公式)
- 駕照體檢表完整版本
評論
0/150
提交評論