版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
數(shù)據(jù)結(jié)構(gòu)計(jì)算機(jī)科學(xué)系施化吉E-mail:第二章抽象數(shù)據(jù)類型和C++類抽象數(shù)據(jù)類型(AbstractDataType,ADT)是用戶在基本數(shù)據(jù)類型基礎(chǔ)上定義和實(shí)現(xiàn)的數(shù)據(jù)類型。一種抽象數(shù)據(jù)類型就是定義了一種新的數(shù)據(jù)元素集合和該數(shù)據(jù)元素集合上所允許的操作集合。抽象數(shù)據(jù)類型在更高一級(jí)的抽象程度上實(shí)現(xiàn)了信息的隱藏和封裝。C++中類的定義體現(xiàn)了抽象數(shù)據(jù)類型的思想。C++中對(duì)于面向?qū)ο蟪绦蛟O(shè)計(jì)的支持,核心部分就是類的定義。2.1抽象數(shù)據(jù)類型
2.1.1從數(shù)據(jù)類型到抽象數(shù)據(jù)類型數(shù)據(jù)類型
定義:一組性質(zhì)相同的值的集合,以及定義于這個(gè)值的集合上的一組操作的總稱。C語(yǔ)言中的基本數(shù)據(jù)類型有
charintfloatdoublevoid
字符型整型浮點(diǎn)型雙精度型無(wú)值數(shù)據(jù)類型規(guī)定了其值的集合中元素的取值范圍和對(duì)這些元素所能采用的操作。
例如:
整型定義了其數(shù)據(jù)集合中的元素的:
可取的值是機(jī)器所能表示的最小負(fù)整數(shù)和最大正整數(shù)之間的任何一個(gè)整數(shù)。
可用的操作有單目運(yùn)算符+、-,雙目運(yùn)算符+、-、*、/、%,關(guān)系運(yùn)算符<、<=、>、>=、==、!=和賦值運(yùn)算符=等。而抽象數(shù)據(jù)類型:抽象數(shù)據(jù)類型定義:是用戶自己定義和實(shí)現(xiàn)的數(shù)據(jù)類型。是指一個(gè)數(shù)學(xué)模型以及定義在該模型上的一組操作。是用以表示應(yīng)用問(wèn)題的數(shù)據(jù)模型,由基本的數(shù)據(jù)類型組成,并包括一組相關(guān)的服務(wù)(或稱操作)。
抽象數(shù)據(jù)類型類似于在計(jì)算機(jī)機(jī)器語(yǔ)言的“位、字節(jié)和字”的基礎(chǔ)上引入“字符、整數(shù)、浮點(diǎn)數(shù)和雙精度數(shù)”等數(shù)據(jù)類型這樣一種方法。這里,“字符、整數(shù)、浮點(diǎn)數(shù)和雙精度數(shù)”等數(shù)據(jù)類型是對(duì)“位、字節(jié)和字”的抽象。
因?yàn)橛?jì)算機(jī)是使用二進(jìn)制定點(diǎn)數(shù)和浮點(diǎn)數(shù)來(lái)實(shí)現(xiàn)數(shù)據(jù)的存儲(chǔ)和運(yùn)算的。從計(jì)算機(jī)硬件系統(tǒng)的角度看,計(jì)算機(jī)能處理的數(shù)據(jù)類型只包括位、字節(jié)和字。高級(jí)程序設(shè)計(jì)語(yǔ)言中引入了字符、整數(shù)、浮點(diǎn)數(shù)、雙精度數(shù)后,程序中就可以直接使用“A”,“57”,“1.3E10”等數(shù)據(jù)表示,而不必使用它們的二進(jìn)制表示。編譯程序會(huì)將這些數(shù)據(jù)值轉(zhuǎn)換成二進(jìn)制碼。
這些數(shù)據(jù)表示就是二進(jìn)制數(shù)據(jù)的抽象。
一個(gè)抽象數(shù)據(jù)類型定義了一種新的數(shù)據(jù)元素集合和數(shù)據(jù)元素集合上所允許的操作集合。
在高級(jí)程序設(shè)計(jì)語(yǔ)言中,由基本數(shù)據(jù)類型可以定義出更高一級(jí)的抽象數(shù)據(jù)類型,如各種表、隊(duì)列、圖甚至窗口、管理器等。
下面以“隊(duì)列”為例,解釋抽象數(shù)據(jù)類型。
一個(gè)隊(duì)列是由若干個(gè)元素組成的一個(gè)序列以及這個(gè)序列上的相關(guān)操作所構(gòu)成。其操作遵循的是“先到先服務(wù)”的原則。當(dāng)新的元素進(jìn)隊(duì)列:加入在隊(duì)列的尾部。
當(dāng)元素出隊(duì)列:總是取出隊(duì)列頭的元素。
隊(duì)列中的元素可以是各種不同類型的對(duì)象。它們可以是整數(shù),也可以是字符,也可以是字符串,甚至可以是關(guān)于一個(gè)學(xué)生的記錄。不管是由什么對(duì)象組成隊(duì)列,都不影響我們對(duì)“隊(duì)列”本質(zhì)的理解?!瓣?duì)列”本質(zhì)就是“先進(jìn)先出”。
所以,可把隊(duì)列看成是一個(gè)抽象數(shù)據(jù)類型。
注意:對(duì)于一個(gè)其數(shù)據(jù)成員完全相同的數(shù)據(jù)類型,如果對(duì)它作不同的“限制”,即定義不同功能的一組操作,就可以形成不同的抽象數(shù)據(jù)類型。如棧和隊(duì)列,可能都是相同的順序表結(jié)構(gòu),但“限制”不同,則具有不同的服務(wù),因此是不同的抽象數(shù)據(jù)類型。抽象數(shù)據(jù)類型與具體應(yīng)用無(wú)關(guān),這樣我們?cè)诰幊绦虻臅r(shí)候就可以把注意力集中在數(shù)據(jù)及其操作的理想模型上。如何描述抽象數(shù)據(jù)類型?2.1.2抽象數(shù)據(jù)類型描述
抽象數(shù)據(jù)類型的特征是把使用和實(shí)現(xiàn)分離開(kāi)來(lái),實(shí)行封裝和信息隱藏。每種抽象數(shù)據(jù)類型的描述應(yīng)包括:抽象數(shù)據(jù)類型的名(稱)數(shù)據(jù)集合的定義每種操作的名稱,該操作的輸入、前置條件、功能、輸出和后置條件等定義。一個(gè)抽象數(shù)據(jù)類型的描述在形式上可繁可簡(jiǎn),描述形式舉例如下:ADT
抽象數(shù)據(jù)類型名
is
Data
數(shù)據(jù)元素集合和數(shù)據(jù)元素間的關(guān)系Operation
構(gòu)造函數(shù)數(shù)據(jù)值的初始化操作1
輸入:用戶輸入的數(shù)據(jù)值
前置條件:執(zhí)行此操作前數(shù)據(jù)所必需的狀態(tài)
動(dòng)作:對(duì)數(shù)據(jù)進(jìn)行的處理
輸出:操作后的返回值描述
后置條件:系統(tǒng)執(zhí)行操作后數(shù)據(jù)的狀態(tài)操作2
……操作3……endADT
抽象數(shù)據(jù)類型名
例2-1
要設(shè)計(jì)一個(gè)擲骰子(zhìtóuzi
)的程序,骰子可設(shè)計(jì)成一個(gè)抽象數(shù)據(jù)類型Dice.
其數(shù)據(jù)類型包括:被擲骰子個(gè)數(shù)N,
擲出骰子的總點(diǎn)數(shù),
每個(gè)骰子的點(diǎn)數(shù);其操作包括:擲骰子,
返回該次投擲的骰子總點(diǎn)數(shù),
打印所擲每個(gè)骰子的點(diǎn)數(shù)。ADTDiceisData//數(shù)據(jù)集合該次投擲骰子的個(gè)數(shù)。這是一個(gè)大于或等于1的整數(shù)。
該次擲出的總點(diǎn)數(shù)。這是一個(gè)大于等于N且小于等于6N的整數(shù)。該次擲出的每個(gè)骰子的點(diǎn)數(shù)。這是一個(gè)表,表中的數(shù)值均為1到6的整數(shù)。
Operation//操作
Constructor
構(gòu)造函數(shù)確定被投擲骰子的個(gè)數(shù)
Toss//擲骰子
輸入:無(wú)前置條件:無(wú)動(dòng)作:擲骰子并計(jì)算總點(diǎn)數(shù)輸出:無(wú)后置條件:投擲的總點(diǎn)數(shù)及每個(gè)骰子的點(diǎn)數(shù)
Total//總點(diǎn)數(shù)輸入:無(wú)前置條件:無(wú)動(dòng)作:檢索該次投擲的總點(diǎn)數(shù)數(shù)據(jù)項(xiàng)輸出:返回該次投擲的總點(diǎn)數(shù)后置條件:無(wú)
DisplayToss//各骰子的點(diǎn)數(shù)輸入:無(wú)前置條件:無(wú)動(dòng)作:打印該次投擲的各骰子的點(diǎn)數(shù)輸出:無(wú)后置條件:無(wú)endADTDice本章的其他內(nèi)容,同學(xué)們?cè)谏蠈W(xué)期已經(jīng)學(xué)過(guò),這里就不再重復(fù)。但請(qǐng)同學(xué)們注意復(fù)習(xí),特別是有關(guān)模板的內(nèi)容。結(jié)束謝謝!2.2類與對(duì)象的基本概念2.2.1類與對(duì)象人類是一個(gè)類(class)。張三是人,李四是人,都是人類的實(shí)例(instance),或稱對(duì)象(object)。一個(gè)類描述一類事物以及該類事物所應(yīng)具有的屬性,如人有身長(zhǎng)、體重、文化程度、性別、年齡等。一個(gè)對(duì)象是類的一個(gè)實(shí)例,它具有確定的屬性值,如張三身高1.80米,體重70公斤,大學(xué)本科,男,21歲。人類只有一個(gè),人類的實(shí)例可以有無(wú)數(shù)個(gè)。對(duì)象是具體的,對(duì)象可以被創(chuàng)建和銷毀。類是抽象的,類是無(wú)所不在的。
例如桌子是一個(gè)類,人們不斷打造各種尺寸和各種風(fēng)格(屬性)的桌子(桌子的實(shí)例),打造桌子,又不斷毀壞桌子。年復(fù)一年,舊的去了,新的又來(lái),但桌子的概念沒(méi)變。它是一個(gè)抽象的概念。應(yīng)該稱它為桌子類,以區(qū)別于打造的具體桌子。在計(jì)算機(jī)領(lǐng)域中,對(duì)象是指在應(yīng)用問(wèn)題中出現(xiàn)的各種實(shí)體、事件、規(guī)格說(shuō)明等。它是由一組屬性值和在這組值上的一組服務(wù)(或稱操作)構(gòu)成的。其中,屬性值確定了對(duì)象的狀態(tài)。例如,一個(gè)顯示在計(jì)算機(jī)屏幕上的圓,作為一個(gè)幾何對(duì)象,它是由圓心坐標(biāo)、半徑長(zhǎng)度、邊線顏色和內(nèi)部顏色等屬性值來(lái)確定位置、大小、顏色等狀態(tài)??梢酝ㄟ^(guò)對(duì)象的服務(wù)來(lái)改變?cè)搶?duì)象的屬性值。例如,服務(wù)move(x,y),將一個(gè)圓移動(dòng)到由實(shí)數(shù)x,y所指定的圓心的新位置上。服務(wù)setRadius(r)、改變圓形的半徑。服務(wù)setEdgeColor(c),改變圓形的邊的顏色和其內(nèi)部顏色。
在面向?qū)ο蟮姆椒ㄖ?類是具有相同操作(服務(wù))與相同數(shù)據(jù)格式(屬性)的對(duì)象的集合。類中的每一個(gè)對(duì)象稱為該類的一個(gè)實(shí)例(instance)。有一個(gè)計(jì)算機(jī)電子郵件系統(tǒng),其主要工作涉及到發(fā)信人寫信、收信人看信,還有電子郵件系統(tǒng)中信的收(receive)、發(fā)(send)及存儲(chǔ)(store)等方面。
例如,你在計(jì)算機(jī)上寫一封信給你的同事John,那么這封信本身是一個(gè)對(duì)象。它具有一般信所有的共性。例如,有信的內(nèi)容和允許你處理的一些方法或動(dòng)作(讀信、寫信、發(fā)信等)。信的內(nèi)容在計(jì)算機(jī)中稱為數(shù)據(jù),而需要處理的一些方法和動(dòng)作,在計(jì)算機(jī)里則統(tǒng)稱為“操作”,將這些信的共性匯集起來(lái)就有了對(duì)象這一概念。用計(jì)算機(jī)軟件的術(shù)語(yǔ)可描述為公式對(duì)象=數(shù)據(jù)+動(dòng)作所有的信的集合就構(gòu)成了類,信中的內(nèi)容不同(即對(duì)象的屬性值不同)。類中的“信”都具有相同的服務(wù):發(fā)信。發(fā)送英文信和發(fā)送日文信的方式是一樣的。處理英文信和處理日文信有相同的方式,還有一些各自獨(dú)有的方式。那么,如果建立兩套平行的信件處理機(jī)制,顯然是不經(jīng)濟(jì)的。可以由“信”這個(gè)類來(lái)定義兩個(gè)類:“英文信”和“日文信”,它們保留了“信”類的服務(wù),并添加上各自獨(dú)立的服務(wù)。這種“保留”稱為“繼承”。
“信”類稱為基類,基類又可稱為父類、超類或泛化類。它具有一般信件的公共操作,讀、寫、發(fā)送信?!坝⑽男拧?、“日文信”稱為派生類,又可稱為子類或特化類。它們繼承了其超類“信”和讀、寫、發(fā)送等操作,但同時(shí)又加上它們自己的“英文”和“日文”特定操作。類、派生類和實(shí)例的關(guān)系如圖2-1所示。
繼承和重用是相輔相成的兩個(gè)概念。要制造新的電冰箱,可以有兩種選擇:
一種是從草圖開(kāi)始;
另一種是對(duì)現(xiàn)有的電冰箱的型號(hào)加以改進(jìn)。也許現(xiàn)有的型號(hào)已經(jīng)令人比較滿意,但如果再增加兩個(gè)功能,會(huì)更加完美。
在原有的型號(hào)基礎(chǔ)上增加兩組電路,很快就制造出來(lái)新的電冰箱了,被賦予一種新的型號(hào)。這就是繼承和重用。
繼承是一種聯(lián)結(jié)類的層次模型,并且允許和鼓勵(lì)類的重用。
層次結(jié)構(gòu)的上層(或祖先類)最具有通用性。下層部分,即后代具有特殊性。
類可以從它的祖先那里繼承方法和實(shí)例變量(即對(duì)象中可訪問(wèn)的數(shù)據(jù)),也可以修改或增加新的方法使之更符合特殊的需要。
2.2.2消息與合作一個(gè)對(duì)象內(nèi)具有過(guò)程和數(shù)據(jù)。外部的用戶或?qū)ο髮?duì)對(duì)象提出的請(qǐng)求,可以稱為對(duì)該對(duì)象發(fā)送消息。在電子郵件系統(tǒng)的例中,對(duì)象“信”具有讀信、寫信或發(fā)信等操作,是由系統(tǒng)設(shè)計(jì)者開(kāi)發(fā)并由對(duì)象“信”提供給用戶的,用戶可以發(fā)送一個(gè)消息(或稱為請(qǐng)求)來(lái)請(qǐng)求所需的服務(wù)。在面向?qū)ο蟮姆椒ㄖ?另一個(gè)經(jīng)常用的概念就是“合作”。
合作是指兩個(gè)對(duì)象之間共同承擔(dān)職責(zé)來(lái)達(dá)到某一目標(biāo)。當(dāng)你告訴對(duì)象“信”,你想把它發(fā)送給John時(shí),你此時(shí)的作用就是一個(gè)客戶。對(duì)象“信”在這里相當(dāng)于一個(gè)服務(wù)器。它提供給你一個(gè)服務(wù)。
你還可以要求別的服務(wù),如讀、寫信等。很多人用客戶/服務(wù)器模型來(lái)描述面向?qū)ο竽P?。在這個(gè)模型中,各個(gè)對(duì)象具有完成不同任務(wù)的職責(zé),客戶對(duì)象可以通過(guò)服務(wù)器對(duì)象來(lái)完成一些任務(wù)。這里把兩個(gè)對(duì)象共同承擔(dān)職責(zé)稱為“合作”。2.2.3多態(tài)性多態(tài)性機(jī)制是指允許不同類的對(duì)象對(duì)同一消息作出響應(yīng)。以前面提到的電子郵件系統(tǒng)為例,現(xiàn)有局域網(wǎng)類對(duì)象LAN和寬域網(wǎng)類對(duì)象WAN,這兩類對(duì)象均可對(duì)來(lái)自對(duì)象“信”的同一消息“發(fā)送給John”作出響應(yīng)。即對(duì)同一個(gè)“發(fā)送給John”操作,可以有不同的實(shí)現(xiàn)方法??梢酝ㄟ^(guò)TCP-IP協(xié)議來(lái)找到John,也可通過(guò)X.25協(xié)議來(lái)找到John,這是在系統(tǒng)運(yùn)行時(shí)由系統(tǒng)決定的。這種動(dòng)態(tài)決定實(shí)現(xiàn)方法的機(jī)制稱為動(dòng)態(tài)聯(lián)編(dynamicbinding)。
一個(gè)多態(tài)性的例子:
學(xué)生類應(yīng)該有一個(gè)計(jì)算成績(jī)的操作。大學(xué)生繼承了中學(xué)生。對(duì)于中學(xué)生,計(jì)算成績(jī)的操作是對(duì)語(yǔ)文、數(shù)學(xué)、英語(yǔ)等課程的計(jì)算,而對(duì)于后繼的大學(xué)生,計(jì)算成績(jī)的操作是對(duì)高等數(shù)學(xué)、計(jì)算機(jī)、普通物理等課程的計(jì)算。
多態(tài)性引用靜態(tài)類型和動(dòng)態(tài)類型。多態(tài)引用的動(dòng)態(tài)類型可以在程序執(zhí)行期間在實(shí)例之間進(jìn)行變化。
在強(qiáng)類型面向?qū)ο蟓h(huán)境中,運(yùn)行時(shí)系統(tǒng)保持所有多態(tài)引用自動(dòng)地和它們的動(dòng)態(tài)類型相聯(lián)結(jié)。
靜態(tài)類型是在程序上下文中由實(shí)體說(shuō)明決定的。在編譯時(shí),系統(tǒng)知道并且決定對(duì)象在運(yùn)行時(shí)可接受的有效類型。這一決定是通過(guò)分析繼承圖實(shí)現(xiàn)的。
2.3面向?qū)ο蟮某绦蛟O(shè)計(jì)方法
傳統(tǒng)的程序設(shè)計(jì)技術(shù)采用的是算法分解。算法分解就是功能分解,該方法將軟件看成一個(gè)處理過(guò)程,將該過(guò)程分解成若干個(gè)步驟的模塊。一般都是在項(xiàng)目被分解成了功能模塊后,再來(lái)考慮數(shù)據(jù)結(jié)構(gòu)。
面向?qū)ο蟮某绦蛟O(shè)計(jì)技術(shù)建立在對(duì)象分解的基礎(chǔ)上,以類設(shè)計(jì)為核心。面向?qū)ο蠓纸鈱④浖闯捎辛己枚x的對(duì)象組成的集合。這些對(duì)象是應(yīng)用領(lǐng)域中實(shí)體的模型化體現(xiàn)。這些對(duì)象以及對(duì)象之間的相互作用構(gòu)成了一個(gè)軟件系統(tǒng)。當(dāng)系統(tǒng)已被分解成為若干個(gè)對(duì)象之后,再去考慮功能的分解。
面向?qū)ο蠓纸庾钪饕膬?yōu)點(diǎn)在于它增進(jìn)了軟件的可重用性。面向?qū)ο蠓纸馔嫦蛩惴ǚ纸庀啾容^更直觀。
程序設(shè)計(jì)階段應(yīng)給出所有對(duì)象的描述,這是構(gòu)成程序的主要部分。同時(shí),設(shè)計(jì)階段也描述對(duì)象間相互作用的控制。對(duì)象設(shè)計(jì)階段明確所有在程序中將要用到的對(duì)象,并給出每個(gè)類的定義,再設(shè)計(jì)出一些程序模塊對(duì)類進(jìn)行測(cè)試。類可以獨(dú)立于系統(tǒng)之外測(cè)試,這是面向?qū)ο蟪绦蛟O(shè)計(jì)的一大特色。
處理控制設(shè)計(jì)階段完成程序的框架設(shè)計(jì),它使用自頂向下方法創(chuàng)建主程序和子程序來(lái)控制對(duì)象間的相互作用。
2.4
C++類與對(duì)象C++對(duì)于面向?qū)ο蟪绦蛟O(shè)計(jì)的支持,核心就是類的定義。類由多個(gè)存放數(shù)據(jù)值的成員和加工數(shù)據(jù)的運(yùn)算組成。這些運(yùn)算稱為成員函數(shù),又稱為方法。成員函數(shù)用來(lái)響應(yīng)發(fā)送給對(duì)象的消息。消息就是對(duì)成員函數(shù)的調(diào)用。定義了一個(gè)類以后,就可以用該類的名字來(lái)聲明該類的對(duì)象。
類可以分為兩個(gè)部分:
公共(public)部分描述用戶使用類的界面。對(duì)于在public域中聲明的數(shù)據(jù)成員和成員函數(shù),程序中其它類的對(duì)象或操作都能請(qǐng)求該類的對(duì)象調(diào)用它們,該界面使用戶不必了解對(duì)象的內(nèi)部細(xì)節(jié)而使用對(duì)象。
私有(private)部分由幫助實(shí)現(xiàn)數(shù)據(jù)抽象的數(shù)據(jù)和內(nèi)部操作組成。私有部分包括private域和protected域,這兩個(gè)域中聲明的數(shù)據(jù)成員和成員函數(shù)只能由該類的對(duì)象和成員函數(shù)以及聲明為友元(friend)的函數(shù)或類的對(duì)象訪問(wèn)。
例2-2
一個(gè)定義類、使用類的例子//TIME1.H//類Time的聲明//成員函數(shù)在TIME1.cpp中定義#ifndefTIME1_H#defineTIME1_H//抽象數(shù)據(jù)類型Time的定義classTime{public:Time();//默認(rèn)構(gòu)造函數(shù)voidsetTime(int,int,int);//設(shè)置時(shí)、分、秒voidprintStandardTime();//打印標(biāo)準(zhǔn)格式的時(shí)間private:inthour;//0-23intminute;//0-59intsecond;//0-59};#endif//TIME1.cpp//類Time的成員函數(shù)的定義#include<iostream.h>#include“TIME1.H”/*類Time的構(gòu)造函數(shù)把每一個(gè)數(shù)據(jù)成員初始化為零,從而保證所有的類Time的對(duì)象具有穩(wěn)定的初始狀態(tài)*/Time::Time(){hour=minute=second=0;}/*設(shè)定一個(gè)新的時(shí)間值,檢查數(shù)據(jù)值的合法性,將非法值設(shè)置為零*/voidTime::setTime(inth,intm,ints){Hour=(h>=0&&h<24)?h:0;Minute=(m>=0&&m<60)?m:0;Second=(s>=0&&s<60)?s:0;}//按標(biāo)準(zhǔn)格式輸出時(shí)間voidtime::printStandardTime(){cout<<((hour==0||hour==12)?12:hour%12)<<“:“<<(minute<10?“0“:““)<<minute<<“:“<<(second<10?“0“:““)<<second<<(hour<12?“AM“:“PM“);}//Example2-2.cpp//使用類Time的程序//注:與文件TIME.cpp一起編譯#include<iostream.h>#include“TIME1.h//測(cè)試類Time的程序main(){Timet;//類Time的實(shí)例對(duì)象tcout<<“Theinitialstandardtimeis“;t.printStandardTime();t.setTime(14,25,9);cout<<“\nstandardtimeaftersetTimeis“;t.printStandardTime();t.setTime(70,70,70);//試圖設(shè)定非法值cout<<”\nAfterattemptinginvalidsettingsstandardtimeis”;t.printStandardTime();cout<<endl;return0;}2.5構(gòu)造函數(shù)和析構(gòu)函數(shù)
構(gòu)造函數(shù)是在創(chuàng)建類的對(duì)象時(shí)自動(dòng)調(diào)用的。類的數(shù)據(jù)成員不能在定義類的時(shí)候初始化,而必須在類的構(gòu)造函數(shù)中初始化,或者在建立類的對(duì)象后再設(shè)置它們的值。
構(gòu)造函數(shù)不能自動(dòng)返回值類型和返回值。可以重載構(gòu)造函數(shù)以便用各種方法初始化類的對(duì)象。構(gòu)造函數(shù)可以使用默認(rèn)參數(shù)。
給構(gòu)造函數(shù)提供默認(rèn)參數(shù)的好處是:即使在調(diào)用構(gòu)造函數(shù)的時(shí)候沒(méi)有提供參數(shù)值,也會(huì)確保按照默認(rèn)的參數(shù)值對(duì)對(duì)象進(jìn)行初始化。
當(dāng)一個(gè)構(gòu)造函數(shù)所有參數(shù)都是默認(rèn)參數(shù)時(shí),該構(gòu)造函數(shù)是默認(rèn)的構(gòu)造函數(shù),也就是說(shuō),在調(diào)用這樣的構(gòu)造函數(shù)時(shí)可以不提供任何參數(shù)。例2-3初始化類Time的對(duì)象
//TIME2.H//類Time的聲明//成員函數(shù)在TIME2.cpp中定義#ifndefTIME2_H#defineTIME2_HclassTime{public:Time(int=0,int=0,int=0);//默認(rèn)構(gòu)造函數(shù)
voidSetTime(int,int,int);voidprintStandardTime();private:inthour;intminute;intsecond;};#endif
//TIME2.cpp//類Time的成員函數(shù)的定義#include<iostream.h>//初始化私有數(shù)據(jù)成員的構(gòu)造函數(shù)//默認(rèn)值是0Time::Time(inthr,intmin,intsec){hour=(hr>=0&&hr<24)?hr:0;minute=(min>=0&&min<60)?min:0;second=(sec>=0&&sec<60)?sec:0;}voidTime::SetTime(inth,intm,ints){hour=(h>=0&&h<24)?h:0;minute=(m>=0&&m<60)?m:0;second=(s>=0&&s<60)?s:0;}voidTime::printStandardTime(){cout<<((hour==0||hour==12)?12:hour%12)<<“:“<<(minute<10?“0“:““)<<minute<<“:“<<(second<10?“0“:““)<<second<<(hour<12?“AM“:“PM“);}#include<iostream.h>#include“TIME2.H”main(){Timet1,t2(2),t3(15,30),t4(12,20,40),t5(28,70,99);cout<<“Constructedwithallargumentsdefaulted:\n“;t1.printStandardTime();cout<<“\nhourspecified;minuteandseconddefaulted:\n“;t2.printStandardTime();cout<<“\nhourandminutespecified;minutedefaulted:\n“;t3.printStandardTime();cout<<“\nhour,minuteandsecondspecified:\n“;t4.printStandardTime();cout<<“\nallinvalidvaluesspecified:\n“;t5.printStandardTime();cout<<endl;return0;}輸出結(jié)果:Constructedwithallargumentsdefaulted12:00:00AMhourspecified;minuteandseconddefaulted:2:00:00AMhourandminutespecified;minutedefaulted:3:30:00PMhour,minuteandsecondspecified:12:20:40PMallinvalidvaluesspecified:12:00:00AM
如果沒(méi)有為類定義構(gòu)造函數(shù),那么編譯器就會(huì)為該類添加一個(gè)默認(rèn)構(gòu)造函數(shù)。默認(rèn)構(gòu)造函數(shù)并不作任何初始化工作,所以在建立該類的對(duì)象時(shí)不能保證有一個(gè)確定的初始狀態(tài)。
析構(gòu)函數(shù)是類的一個(gè)特殊的成員函數(shù),析構(gòu)函數(shù)的標(biāo)志是在類的名字的前面加上字符“”。
析構(gòu)函數(shù)是構(gòu)造函數(shù)的反向操作。當(dāng)撤銷一個(gè)類的對(duì)象時(shí),該類的析構(gòu)函數(shù)就自動(dòng)被調(diào)用,在系統(tǒng)回收對(duì)象所占用的內(nèi)存空間之前先做的一些清理工作。析構(gòu)函數(shù)沒(méi)有參數(shù)和返回值。
一個(gè)類只能有一個(gè)析構(gòu)函數(shù),重載析構(gòu)函數(shù)是不允許的。當(dāng)類的對(duì)象包含動(dòng)態(tài)分配的內(nèi)存時(shí),為類提供析構(gòu)函數(shù)是合適的。
析構(gòu)函數(shù)和構(gòu)造函數(shù)通常是被自動(dòng)調(diào)用的,其調(diào)用順序取決于建立和撤銷對(duì)象的順序。一般來(lái)說(shuō),調(diào)用析構(gòu)函數(shù)的順序與調(diào)用構(gòu)造函數(shù)的順序相反。但是,對(duì)象的作用域會(huì)改變析構(gòu)函數(shù)的順序。對(duì)聲明為全局的對(duì)象來(lái)說(shuō),其構(gòu)造函數(shù)在聲明該對(duì)象的時(shí)候調(diào)用,
相應(yīng)的析構(gòu)函數(shù)在程序退出該對(duì)象的作用域的時(shí)候被調(diào)用。靜態(tài)局部對(duì)象的構(gòu)造函數(shù)只在聲明該對(duì)象的時(shí)候調(diào)用一次,相應(yīng)的析構(gòu)函數(shù)在程序終止的時(shí)候被調(diào)用。
例2-4
類ConstructAndDestruct
//CONSTRUCT.H//類ConstructAndDestruct的定義//成員函數(shù)在CONSTRUCT.CPP中定義#ifndefCONSTRUCT_H#defineCONSTRUCT_HclassConstructAndDestruct{public:ConstructAndDestruct(int);//構(gòu)造函數(shù)~ConstructAndDestruct();//析構(gòu)函數(shù)private:intdata;};#endif(接下頁(yè))//CONSTRUCT.CPP//類ConstructAndDestruct的成員函數(shù)的定義#include<iostream.h>#include“construct.h“ConstructAndDestruct::ConstructAndDestruct(intvalue){data=value;cout<<“Object“<<data<<“constructor“;}ConstructAndDestruct::~ConstructAndDestruct(){cout<<“Object“<<data<<“destructor“<<endl;}//Example2-4.CPP//演示構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用順序#include<iostream.h>#include“construct.h“voidconstruct(void);//函數(shù)原型ConstructAndDestructfirst(1);//全局對(duì)象(接下頁(yè))main(){
cout<<“(globalconstructbeforemain)\n“;ConstructAndDestructsecond(2);//局部對(duì)象cout<<“(localautomaticinmain)\n“;
staticConstructAndDestructthird(3);//局部對(duì)象
cout<<“(localstaticinmain)\n“;
construct();//調(diào)用建立對(duì)象的函數(shù)
ConstructAndDestructfourth(4);//局部對(duì)象
cout<<“(localautomaticinmain)\n“;
return0;}(接下頁(yè))//建立函數(shù)的對(duì)象voidconstruct(void){ConstructAndDestructfifth(5);cout<<“(localautomaticinconstruct)\n“;ConstructAndDestructsixth(6);cout<<“(localstaticinconstruct)\n“;ConstructAndDestructseventh(7);cout<<“(localautomaticinconstruct)\n“;}輸出結(jié)果:Object1constructor(globalconstructbeforemain)Object2constructor(localautomaticinmain)Object3constructor(localstaticinmain)Object5constructor(localautomaticinconstruct)Object6constructor(localstaticinconstruct)Object7constructor(localautomaticinconstruct)
(接下頁(yè))Object7destructorObject6destructorObject5destructorObject4constructor(localautomaticinmain)Object4destructorObject2destructorObject3destructorObject1destructor2.6工具函數(shù)
并不是所有的成員函數(shù)都要設(shè)定成公有的。一些成員函數(shù)可以是私有的,它們用作其它成員函數(shù)的工具函數(shù)。成員函數(shù)可以分為許多種:
讀取和返回私有數(shù)據(jù)成員值的函數(shù);設(shè)定私有數(shù)據(jù)成員值的函數(shù);實(shí)現(xiàn)類的特點(diǎn)的函數(shù);完成類的各種基本操作的函數(shù)(如初始化類的對(duì)象、給類的對(duì)象賦值、實(shí)現(xiàn)類與內(nèi)部類型或與其它類之間的轉(zhuǎn)換,處理類的對(duì)象所占用的內(nèi)存等等)。訪問(wèn)函數(shù)可以讀取和顯示數(shù)據(jù)。訪問(wèn)函數(shù)還經(jīng)常用來(lái)測(cè)試條件的真假,這類函數(shù)通常叫做判斷函數(shù)。函數(shù)IsEmpty是一個(gè)判斷函數(shù),它用于諸如鏈表、堆?;蜿?duì)列等等的包容器類。IsFull判斷函數(shù)用于測(cè)試包容器對(duì)象中是否還有剩余的空間。例2-5的程序演示了工具函數(shù)的使用。工具函數(shù)不是類的接口,而是類的私有成員,用于支持類的公有成員函數(shù)的操作。類的客戶不能直接使用工具函數(shù)。
例2-5
演示工具函數(shù)的使用
//SALESP.H//類SalesPerson的定義//成員函數(shù)在SALESP.CPP中定義
#ifndefSALESP_H#defineSALESP_HclassSalesPerson{public:SalesPerson();//構(gòu)造函數(shù)
voidsetSales();//由用戶提供售貨額
voidprintAnnualSales();private:
doublesales[13];//12個(gè)月的售貨額
doubletotalAnnualSales();//工具函數(shù)};#endif//SALESP.CPP//類SalesPerson的成員函數(shù)#include<iostream.h>#include<iomanip.h>#include“salesp.h“//構(gòu)造函數(shù)對(duì)數(shù)組的初始化SalesPerson::SalesPerson(){for(inti=0;i<=12;i++)sales[i]=0.0;}//設(shè)置十二個(gè)月銷售額的函數(shù)voidSalesPerson::setSales(){inti; for(inti=1;I<=12;I++){
cout<<“Entersalesamountformonth“<<i<<“:“;
cin>>sales[i];
}}//Example2-5.CPP//演示工具函數(shù)的使用//與SALESP.CPP一起編譯#include“salesp.h“main(){SalesPersons;//建立類SalesPerson的對(duì)象ss.setSales();s.printAnnualSales();
return0;}輸出結(jié)果:Entersalesamountformonth1:5314.76Entersalesamountformonth2:4292.38Entersalesamountformonth3:4589.83Entersalesamountformonth4:5534.03
Entersalesamountformonth5:4376.34Entersalesamountformonth6:5698.45Entersalesamountformonth7:4439.22Entersalesamountformonth8:5893.57Entersalesamountformonth9:4909.67Entersalesamountformonth10:5123.45Entersalesamountformonth11:4024.97Entersalesamountformonth12:5923.92Totalannualsalesare:$60120.592.7繼承
繼承是軟件重用的一種形式。實(shí)現(xiàn)的方法就是從現(xiàn)有的類(基類)建立新的類(派生類)。新類繼承了現(xiàn)有類的屬性和行為,并且為了使新類具有自己所需的功能,新類還可以對(duì)這些屬性和行為進(jìn)行修飾。軟件重用縮短了程序的開(kāi)發(fā)時(shí)間,使開(kāi)發(fā)人員可以重用已經(jīng)測(cè)試和調(diào)試好了的高質(zhì)量的軟件。在建立一個(gè)派生類時(shí),程序員可以讓其繼承基類的數(shù)據(jù)成員和成員函數(shù),而不必重新編寫新的數(shù)據(jù)成員和成員函數(shù),派生類本身也可能成為未來(lái)派生類的基類。
用類似的方法處理基類對(duì)象和派生類對(duì)象是可能的?;惖膶傩院托袨楸硎隽嘶悓?duì)象和派生類對(duì)象的共性。從基類公有派生出來(lái)的所有對(duì)象都可以作為基類對(duì)象處理。
例2–6
類point的定義和派生類circle//POINT.H//類point的定義#ifndefPOINT_H#definePOINT_H#include<iostream.h>classPoint{friendostream&operator<<(ostream&,constpoint&);public:Point(float=0,float=0);//默認(rèn)的構(gòu)造函數(shù)voidsetPoint(float,float);//設(shè)置坐標(biāo)值floatgetX()const{returnx;}floatgetY()const{returny;}protected://允許派生類訪問(wèn)
floatx,y;//點(diǎn)(類Point的對(duì)象)的x和y坐標(biāo)};#endif
//POINT.CPP//定義類Point的成員函數(shù)#include<iostream.h>#include"point.h"http://類Point的構(gòu)造函數(shù)Point::Point(floata,floatb){x=a;y=b;}//設(shè)置點(diǎn)的x和y坐標(biāo)voidPoint::setPoint(floata,floatb){x=a;y=b;}//用重載的流插入運(yùn)算符輸出點(diǎn)的坐標(biāo)ostream&operator<<(ostream&output,constPoint&p){ output<<'['<<p.x<<","<<p.y<<']';
returnoutput;//使得能夠連續(xù)調(diào)用}//CIRCLE.H//類Circle的定義#ifndefCIRCLE_H#defineCIRCLE_H#include<iostream.h>#include<iomanimp.h>#include"point.h"classCircle:publicPoint{friendostream&operator<<(ostream&,constCircle&);public://默認(rèn)的構(gòu)造函數(shù)Circle(floatr=0.0,floatx=0,floaty=0);voidsetRadius(float);//設(shè)置半徑值floatgetRadius()const;//返回半徑值floatarea()const;//計(jì)算圓的面積protected:
floatradius;};#endif
//CIRCLE.CPP//定義類Circle的成員函數(shù)#include"circle.h“//先用成員初始化值調(diào)用類Point的構(gòu)造函數(shù),//然后再調(diào)用類Circle的構(gòu)造函數(shù)初始化半徑值Circle::Circle(floatr,floata,floatb):Point(a,b)//調(diào)用基類的構(gòu)造函數(shù){radius=r;}//設(shè)置圓的半徑值floatCircle::getRadius()const{returnradius;}
//計(jì)算圓的面積floatCircle::area()const{return3.14159*radius*radius;}
//以Center=[x,y];Radius=#.##形式輸出一個(gè)圓ostream&operator<<(ostream&output,constCircle&c){ output<<"Center=["<<c.x<<","<<c.y <<"];Radius="<<setiosflags(ios::showpoint) <<setprecision(2)<<c.radius;
returnoutput;//使得能夠連續(xù)調(diào)用}CIRCLE-1.CPP//把基類指針強(qiáng)制轉(zhuǎn)換為派生類指針#include<iostream.h>#include<iomanip.h>#include"point.h"#include"circle.h“intmain(){Point*pointPtr,p(3.5,5.3);Circle*circlePtr,c(2.7,1.2,8.9);
cout<<“Pointp:”<<p<<“\nCirclec:”<<c<<endl;/*Circle的對(duì)象還是作為Circle對(duì)象處理,但是用了一些類型轉(zhuǎn)換*/pointPtr=&c;//把Circle對(duì)象的地址賦給pointPtrcirclePtr=(Circle*)pointPtr;//把基類指針轉(zhuǎn)換為派生類指針
cout<<"\nAreaofc(viacirclePtr):" <<circlePtr->area()<<endl;//危險(xiǎn):把Point的對(duì)象作為Circle對(duì)象處理
pointPtr=&p;//把Point對(duì)象的地址賦給pointPtrcirclePtr=(Circle*)pointPtr;//把基類指針轉(zhuǎn)換為派生類指針
cout<<"/nRadiusofobjectcirclePtrpointsto:"<<circlePtr->getRadius()<<endl;
return0;}
輸出結(jié)果:Pointp:[3.5,5.3]Circlec:Center=[1.2,8.9];Radius=2.70Areaofc(viacirclePtr):23RadiusofobjectcirclePtrpointsto:9.5e-039
從一個(gè)基類派生一個(gè)類時(shí),繼承基類的方式除了公有繼承以外,還有受保護(hù)(protected)繼承和私有繼承(private),后兩種繼承不常用。
派生類不繼承基類的構(gòu)造函數(shù)和賦值運(yùn)算符,但是派生類的構(gòu)造函數(shù)和賦值運(yùn)算符能調(diào)用基類的構(gòu)造函數(shù)和賦值運(yùn)算符。派生類的構(gòu)造函數(shù)總是先調(diào)用其基類構(gòu)造函數(shù)來(lái)初始化類中的基類成員。
如果省略了派生類的構(gòu)造函數(shù),那么就由默認(rèn)構(gòu)造函數(shù)調(diào)用基類的構(gòu)造函數(shù)。析構(gòu)函數(shù)的調(diào)用順序和調(diào)用構(gòu)造函數(shù)的順序相反,因此派生類的析構(gòu)函數(shù)在基類析構(gòu)函數(shù)之前調(diào)用。
2.8this指針的使用
在C++中,每個(gè)對(duì)象都有一個(gè)指向自身的指針。該指針?lè)Q為this指針。在引用對(duì)象內(nèi)部的成員時(shí),this指針是一個(gè)隱含的參數(shù),即不需顯式寫出它,就可直接訪問(wèn)對(duì)象內(nèi)部的成員。當(dāng)然,也可以明確地使用this指針。
每一個(gè)對(duì)象都可以通過(guò)使用this指針來(lái)確定其自身的地址。這就是為什么當(dāng)成員函數(shù)引用該類的一個(gè)特定對(duì)象的另一個(gè)成員時(shí),C++能保證該函數(shù)能正確地引用了該對(duì)象。例2-7
用this指針引用對(duì)象的成員
//Example2-7.cpp#include<iostream.h>classUsingThis{public:UsingThis(int=99);
voidprint()const;private:inty;};UsingThis::UsingThis(inta){y=a;}//構(gòu)造函數(shù)voidUsingThis::print()const{
cout<<”y=”<<y<<”\nthis->y=”<<this->y<<”\n(*this).y=”<<(*this).y<<’\n’;}main(){UsingThisu(88);u.print();return0;}輸出結(jié)果:y=88this->y=88(*this).y=88
2.9虛函數(shù)、多態(tài)性以及動(dòng)態(tài)聯(lián)編2.9.1虛函數(shù)和多態(tài)性
虛函數(shù)(virtualfunction)和多態(tài)性(polymorphism)使得設(shè)計(jì)和實(shí)現(xiàn)易于擴(kuò)展的系統(tǒng)成為可能。
在程序開(kāi)發(fā)中,不論類是否已經(jīng)建立,程序員都可以利用虛函數(shù)和多態(tài)性先編寫處理這些類的對(duì)象的程序。如果有些類要從基類派生,那么程序可以提供操作基類對(duì)象的通用框架,然后由派生類對(duì)象對(duì)該框架作很好的加工。例如,一個(gè)多邊形可以是矩形(Rectangle)、正方形(Square)、三角形(Triangle)等,它們都可成為多邊形類(Polygon)的派生類。為了高效的繪制各自的形狀,每一個(gè)類都需要有一個(gè)自己的draw函數(shù),這些函數(shù)的程序代碼是不相同的。當(dāng)需要繪制一個(gè)形狀時(shí),不管它是什么形狀,把它作為基類polygon的對(duì)象來(lái)處理是再好不過(guò)了。然后,只需要簡(jiǎn)單的調(diào)用基類polygon的函數(shù)draw,并讓程序動(dòng)態(tài)的確定使用哪一個(gè)派生類的draw函數(shù)。
為了使這種方法可行,我們把基類中的函數(shù)聲明為虛函數(shù)draw,然后在每個(gè)派生類中重新定義函數(shù)draw,使之能夠繪制合適的形狀。虛函數(shù)的聲明方法是在基類的函數(shù)原型前加上關(guān)鍵字virtual。
在類的繼承層次中,如果某一個(gè)類的定義里聲明了一個(gè)虛函數(shù),那么從該類之后的繼承層次結(jié)構(gòu)中都是虛函數(shù)。
沒(méi)有定義虛函數(shù)的派生類就簡(jiǎn)單地繼承其直接基類的虛函數(shù);如果在派生類中重新定義虛函數(shù),那么重新定義的虛函數(shù)應(yīng)當(dāng)與其基類的虛函數(shù)有相同的返回類型,參數(shù)個(gè)數(shù)和參數(shù)類型。如果在基類的虛函數(shù)原型中加上記號(hào)“=0”,該虛函數(shù)就成為純虛函數(shù)。
純虛函數(shù)的實(shí)現(xiàn)代碼應(yīng)當(dāng)由派生類提供,記號(hào)“=0”使得基類成為一個(gè)抽象類,抽象類不能用來(lái)建立實(shí)例化的對(duì)象。其唯一用途是為其他類提供合適的基類,其他類可從它這里繼承接口。例如,基類polygon有一個(gè)純虛函數(shù)virtualvoiddraw()=0,因此polygon就成為抽象類,它沒(méi)有實(shí)例化對(duì)象,也不用來(lái)建立實(shí)例化對(duì)象,所有操作都沒(méi)有實(shí)現(xiàn)代碼?;恜olygon作為抽象類,將使得draw成為所有的派生類的接口。
C++支持多態(tài)性,所謂多態(tài)性是指“一個(gè)接口,多個(gè)算法”,即允許把一個(gè)接口用于一類行為。不同的通過(guò)繼承而相關(guān)的類,它們的對(duì)象能夠?qū)ν粋€(gè)函數(shù)調(diào)用作出不同的響應(yīng)。
例如,有一個(gè)程序定義了三種不同數(shù)據(jù)類型的順序表:一個(gè)用于整數(shù)型的值,一個(gè)用于浮點(diǎn)型的值,一個(gè)用于長(zhǎng)整數(shù)型的值。根據(jù)多態(tài)性,我們可以為Insert()和Remove()各創(chuàng)建三個(gè)函數(shù),編譯程序根據(jù)調(diào)用Insert()和Remove()時(shí)所帶參數(shù)的數(shù)據(jù)類型,選擇適當(dāng)?shù)膶?shí)現(xiàn)函數(shù)。
多態(tài)性是通過(guò)虛函數(shù)實(shí)現(xiàn)的,當(dāng)通過(guò)基類指針引用一個(gè)虛函數(shù)時(shí),C++會(huì)在與對(duì)象相關(guān)聯(lián)的派生類中正確的選擇和使用重定義的函數(shù)。
使用虛函數(shù)和多態(tài)性能夠使成員函數(shù)的調(diào)用根據(jù)接收到該調(diào)用的對(duì)象的類型產(chǎn)生不同的動(dòng)作。
多態(tài)性給了程序員極大的靈活性。多態(tài)性提高了軟件系統(tǒng)的可擴(kuò)展性。
盡管不能實(shí)例化抽象類的對(duì)象,但可以聲明抽象(基)類的指針。當(dāng)實(shí)例化了具體類的對(duì)象后,可以用這種指針使派生類對(duì)象具有多態(tài)操作的能力。
例2-8
用虛函數(shù)和多態(tài)性計(jì)算工資//EMPLOY2.H//抽象基類Employee#ifndefEMPLOY2_H#defineEMPLOY2_HclassEmployee{public: Employee(const
char*,const
char*);~Employee();
constchar*getFirstName()const;
constchar*getLastName()const;//純虛函數(shù)使類Employee成為抽象基類virtualfloatearnings()const=0;//純虛函數(shù)virtualvoidprint()const=0;//純虛函數(shù)
private:char*firstName;
char*lastName;};#endif
//EMPLOY2.CPP//定義抽象基類Employee成員函數(shù)//注:虛函數(shù)沒(méi)有定義#include<iostream.h>#include<string.h>#include<assert.h>#include"employ2.h"/*構(gòu)造函數(shù)動(dòng)態(tài)地為名和姓分配內(nèi)存,并用函數(shù)strcpy把名和姓拷貝到對(duì)象中*/Employee::Employee(constchar*first,constchar*last){firstName=new
char[strlen(first)+1];
assert(firstName!=0);//測(cè)試內(nèi)存分配是否成功strcpy(firstName,first);lastName=newchar[strlen(last)+1]; assert(lastName!=0);//測(cè)試內(nèi)存分配是否成功strcpy(lastName,last);}
//析構(gòu)函數(shù)釋放動(dòng)態(tài)分配的內(nèi)存Employee::~Employee(){delete[]firstName;delete[]lastName;}//返回指向雇員名的指針constchar*Employee::getFirstName()const{ /*const限定符防止調(diào)用者修改私有數(shù)據(jù)。為防止引用沒(méi)有定義的指針,
調(diào)用者應(yīng)該在析構(gòu)釋放內(nèi)存之前拷貝返回的字符串*/
returnfirstName;//調(diào)用者必須釋放內(nèi)存}
//返回指向雇員姓的指針constchar*Employee::getLastName()const{/*const限定符防止調(diào)用者修改私有數(shù)據(jù)。為防止引用沒(méi)有定義的指針,調(diào)用者應(yīng)該在析構(gòu)釋放內(nèi)存之前拷貝返回的字符串*/
returnlastName;//調(diào)用者必須釋放內(nèi)存}//BOSS1.H//從類Employee派生出來(lái)的類Boss#ifndefBOSS1_H#defineBOSS1_H#include"employ2.h"
classBoss:publicEmployee{public:Boss(constchar*,constchar*,float=0.0);voidsetWeeklySalary(float);virtualfloatearnings()const;virtualvoidprint()const;private: floatweeklySalary;};#endif//BOSS1.CPP//定義類Boss的成員函數(shù)#include<iostream.h>#include"boss1.h“
//類Boss的構(gòu)造函數(shù)Boss::Boss(constchar*first,constchar*last,floats) :Employee(first,last)//調(diào)用基類的構(gòu)造函數(shù){weeklySalary=s>0?s:0;}//設(shè)置老板的工資voidBoss::setWeeklySalary(floats){weeklySalary=s>0?s:0;}//返回老板工資floatBoss::earnings()const{returnweeklySalary;}//打印老板的姓名voidBoss::print()const{cout<<"\nBoss:"<<getFirstName()<<''<<getLastName();}MIS1.H//從類Employee派生出來(lái)的類CommissionWorker#ifndefCOMMIS1_H#defineCOMMIS1_H#include"employ2.h“classCommissionWorker:publicEmployee{public:CommissionWorker(constchar*,constchar*,float=0.0,float=0.0,int=0);voidsetSalary(float);voidmission(float);voidSetQuantity(int);virtualfloatearnings()const;virtualvoidprint()const;private:floatsalary;//每周的基本工資 floatcommission;//每件產(chǎn)品的回扣量 intquantity;//一周的銷售量};#endifMIS1.CPP//定義類CommissionWorker的成員函數(shù)#include<iostream.h>#include"commis1.h"http://類CommissionWorker的構(gòu)造函數(shù)missionWorker(constchar*first, constchar*last,floats,floatc,intq):Employee(first,last)//調(diào)用基類的構(gòu)造函數(shù){salary=s>0?s:0;commission=c>0?c:0;quantity=q>0?q:0;}//設(shè)置銷售員每周的基本工資voidCommissionWorker::setSalary(floats){salary=s>0?s:0;}//設(shè)置銷售員的回扣額voidmission(floatc){ commission=c>0?c:0; }//設(shè)置銷售員的銷售量voidCommissionWorker::SetQuantity(intq){quantity=q>0?q:0;}//計(jì)算銷售員的收入floatCommissionWorker::earnings()const{returnmission*quantity;}//打印銷售員的姓名voidCommissionWorker::print()const{ cout<<"\nCommissionWorker:"<<getFirstName()<<''<<getLastName();}//PIECE1.H//從類Employee派生出來(lái)的類PieceWorker
#ifndefPIECE1_H#definePIECE1_H#include"employ2.h“classPieceWorker:publicEmployee{public: PieceWorker(constchar*,constchar*,float=0.0,int=0);voidsetWage(float);
voidSetQuantity(int);
virtualfloatearnings()const; virtualvoidprint()const;private:
floatwagePetPiece;//每件產(chǎn)品的報(bào)酬
intquantity;//一周生產(chǎn)的產(chǎn)品數(shù)量};#endif
//PIECE1.CPP//定義類PieceWorker的成員函數(shù)#include<iostream.h>#include"piece1.h“}//類PieceWorker的構(gòu)造函數(shù)PieceWorker::PieceWorker(constchar*first,constchar*last,floatw,intq) :Employee(first,last)//調(diào)用基類的構(gòu)造函數(shù){wagePetPiece=w>0?w:0; quantity=q>0?q:0;//設(shè)置每件產(chǎn)品的報(bào)酬voidPieceWorker::setWage(floatw){wagePerPiece=w>0?w:0;}//設(shè)置生產(chǎn)的產(chǎn)品數(shù)量voidPieceWorker::SetQuantity(intq){quantity=q>0?q:0; }//計(jì)算計(jì)件工的收入floatPieceWorker::earnings()const
{returnquantity*wagePetPiece;}
//打印計(jì)件工的姓名voidPieceWorker::print()const{
cout<<"\nPieceWorker:"<<getFirstName()<<''<<getLastName();}//HOURLY1.H//從類Employee派生出來(lái)的類HourlyWorker
#ifndefHOURLY1_H#defineHOURLY1_H#include"employ2.h"
classHourlyWorker:publicEmployee{public:HourlyWorker(constchar*,constchar*,float=0.0,float=0.0);
voidsetWage(float); voidsetHours(float);
virtualfloatearnings()const;virtualvoidprint()const;private:floatwage;//每小時(shí)報(bào)酬
floathours;//一周工作時(shí)數(shù)};#endif
//HOURLY1.CPP//定義類HourlyWorker的成員函數(shù)#include<iostream.h>#include"hourly1.h“//類HourlyWorker的構(gòu)造函數(shù)HourlyWorker::HourlyWorker(constchar*first,constchar*last,floatw,floath) :Employee(first,last)//調(diào)用基類的構(gòu)造函數(shù){wage=w>0?w:0; hours=h>=0&&h<168?h:0;}//設(shè)置每小時(shí)報(bào)酬voidHourlyWorker::setWage(floatw){ wage=w>0?w:0; }//設(shè)置工作時(shí)數(shù)voidHourlyWorker::setHours(floath){ hours=h>=0&&h<168?h:0;}//返回小時(shí)工的收入floatHourlyWorker::earnings()const
{returnwage*hours;}//打印小時(shí)工的姓名voidHourlyWorker::print()const{cout<<"\nHourlyWorker:"<<getFirstName()<<''<<getLastName();}2.9.2動(dòng)態(tài)聯(lián)編動(dòng)態(tài)聯(lián)編是指在系統(tǒng)運(yùn)行時(shí)確定對(duì)象的類型,動(dòng)態(tài)聯(lián)編提供了很大的便利性,有時(shí)也稱為后期聯(lián)編。
在面向?qū)ο蠓椒ㄖ?動(dòng)態(tài)聯(lián)編是和多態(tài)性及繼承性緊密相關(guān)的。因?yàn)?過(guò)程具有多態(tài)引用機(jī)制主要是依賴于引用的動(dòng)態(tài)類型。例2-9給出了使用上一節(jié)所定義的類的測(cè)試程序。我們將以此例來(lái)討論靜態(tài)聯(lián)編和動(dòng)態(tài)聯(lián)編。程序首先將ptr聲明為基類指針類型Employee*。Main()函數(shù)中的四小段代碼是類似的,因此我們只討論處理Boss對(duì)象的第一段代碼。例2-9
根據(jù)員工類型計(jì)算工資的程序
//Example2-9.cpp//類Employee層次結(jié)構(gòu)的測(cè)試程序
#include<iostream.h>#include<iomanip.h>#include"empoly2.h"#include"boss.h"#include"commis1.h"#include"piece1.h"#include"hourly1.h“main(){//設(shè)置輸出格式cout<<setiosflags(ios::showpoint)<<setprecision(2);Employee*ptr;//基類指針Bossb("John","Smith",800.00);ptr=&b;//指向派生類對(duì)象的基類指針ptr->print();//動(dòng)態(tài)聯(lián)編cout<<"earned$"<<ptr->earnings();//動(dòng)態(tài)聯(lián)編b.print();//靜態(tài)聯(lián)編cout<<“earned$”<<b.earnings();//靜態(tài)聯(lián)編CommissionWorkerc("Sue","Jones",200.0,3.0,150);ptr=&c;//指向派生類對(duì)象的基類指針ptr->print();//動(dòng)態(tài)聯(lián)編cout<<"earned$"<<ptr->earnings();//動(dòng)態(tài)聯(lián)編c.print();//靜態(tài)聯(lián)編cout<<"earned$"<<c.earnings();//靜態(tài)聯(lián)編PieceWorkerp("Bob","Lewis",2.5,2
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2024年度程海保護(hù)區(qū)域生物多樣性保護(hù)合同
- 2024上海市環(huán)保工程項(xiàng)目合同
- 2024年數(shù)據(jù)中心機(jī)柜分租合同
- 2024年建筑聯(lián)盟:合作伙伴合同書
- 2024年影視制作拍攝合同
- 2024年房屋買賣合同延期規(guī)定
- 2024年搬家貨運(yùn)服務(wù)協(xié)議
- 2024年新型基礎(chǔ)設(shè)施建設(shè)合同
- DB4117T 219-2019 鳊魚養(yǎng)殖技術(shù)規(guī)程
- DB4106T 103-2023 麥套辣椒生產(chǎn)技術(shù)規(guī)程
- 2025年九省聯(lián)考新高考 政治試卷(含答案解析)
- 2024年統(tǒng)編版小學(xué)六年級(jí)《道德與法治》上冊(cè)第四單元 法律保護(hù)我們健康成長(zhǎng) 9.《知法守法 依法維權(quán)》 第一課時(shí) 課件
- 期中測(cè)試卷-2024-2025學(xué)年語(yǔ)文六年級(jí)上冊(cè)統(tǒng)編版
- 學(xué)校消防系統(tǒng)維保及檢測(cè)總體服務(wù)方案
- 網(wǎng)絡(luò)安全試題題庫(kù)及參考答案
- 終極戰(zhàn)略規(guī)劃指南:深度剖析Cross SWOT分析、市場(chǎng)洞察與內(nèi)部能力優(yōu)化的綜合行動(dòng)方案
- 《白描花卉妙筆生》 課件 2024-2025學(xué)年嶺南美版(2024) 初中美術(shù)七年級(jí)上冊(cè)
- 園區(qū)出入管理系統(tǒng)施工方案
- 數(shù)據(jù)可視化說(shuō)課 高中信息技術(shù)
- 混凝土結(jié)構(gòu)施工圖平面整體表示方法制圖規(guī)則和詳圖
- 2024年二季度靈活就業(yè)調(diào)查報(bào)告
評(píng)論
0/150
提交評(píng)論