第8章-繼承和派生_第1頁
第8章-繼承和派生_第2頁
第8章-繼承和派生_第3頁
第8章-繼承和派生_第4頁
第8章-繼承和派生_第5頁
已閱讀5頁,還剩32頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

第8章繼承和派生

在C++中可重用性是通過繼承(inheritance)這一機(jī)制來實(shí)現(xiàn)的。繼承是C++的一個(gè)重要組成部分。8.1繼承和派生的概念

在C++中,所謂“繼承”就是在一個(gè)已存在的類的基礎(chǔ)上建立一個(gè)新的類。一個(gè)新類從已有的類那里獲得其已有特性,這種現(xiàn)象稱為類的繼承。通過繼承,一個(gè)新建子類從已有的父類那里獲得父類的特性。從另一角度說,從已有的類(父類)產(chǎn)生一個(gè)新的子類,稱為類的派生。類的繼承是用已有的類來建立專用類的編程技術(shù)。8.1.1基類與派生類

1.繼承與派生交通工具飛機(jī)滑翔機(jī)直升飛機(jī)噴氣式飛機(jī)交通工具飛機(jī)滑翔機(jī)直升飛機(jī)噴氣式飛機(jī)已存在的類(例如“交通工具”)稱為“基類”或“父類”。新建立的類(例如“飛機(jī)”)稱為“派生類”或“子類”。一個(gè)基類可以派生出多個(gè)派生類,每一個(gè)派生類又可以作為基類再派生出新的派生類,因此基類和派生類是相對(duì)而言的。2.基類與派生類請注意圖中箭頭的方向,在本書中約定,箭頭表示繼承的方向,從派生類指向基類。8.1.2繼承與派生的作用1.避免公用代碼的重復(fù)開發(fā),在減少代碼和數(shù)據(jù)冗余的同時(shí),節(jié)省程序開發(fā)的時(shí)間,提高程序開發(fā)的效率和質(zhì)量。2.通過增強(qiáng)代碼一致性來減少模塊間的接口和界面。3.通過層次關(guān)系來組織對(duì)象,使得高層類作為低層類的抽象,有利于程序員掌握對(duì)象的共性,在此基礎(chǔ)上,就能更快地掌握低層類中的個(gè)性特征,給編程與代碼重用帶來方便。8.1.3派生類的聲明聲明一個(gè)派生類的一般格式為:class派生類名:派生存取說明符(可?。┗惷鹻 //派生類新增的數(shù)據(jù)成員和成員函數(shù)};

派生類名”是要從基類派生出的新類的名字,“基類名”是一個(gè)已經(jīng)定義好的基類的名字,“派生存取說明符”可以是關(guān)鍵字public或protected或private,派生存取說明符的作用會(huì)在后面詳細(xì)介紹,“派生存取說明符”可以省略,默認(rèn)為private,即私有派生。//定義一個(gè)基類(Student類)classStudent{ public: charname[10];//姓名 intage; //年齡 charsex; //性別 charclassname[20]; //班級(jí)名稱};//定義一個(gè)派生類(GraduateStudent類)classGraduateStudent:publicStudent{ public: charAdvisorname[10];//導(dǎo)師 intqualifiergrade; //資格考試分};8.2派生類成員的訪問控制

8.2.1派生類成員訪問控制簡介從一個(gè)基類派生出一個(gè)子類時(shí),可以通過指定派生時(shí)的存取說明符來實(shí)現(xiàn)對(duì)派生類成員的訪問控制。既然派生類中包含基類成員和派生類自己增加的成員,就產(chǎn)生了這兩部分成員的關(guān)系和訪問屬性的問題。在建立派生類的時(shí)候,并不是簡單地把基類的私有成員直接作為派生類的私有成員,把基類的公用成員直接作為派生類的公用成員。實(shí)際上,對(duì)基類成員和派生類自己增加的成員是按不同的原則處理的。8.2.2private、protected與public類成員

1.private類成員一個(gè)類中的私有(private)成員(包括數(shù)據(jù)成員和成員函數(shù))只能被它們所在類的成員函數(shù)和友元函數(shù)訪問,在C++中類成員存取說明符缺省的情況下的存取特征都是私有的(private)?!纠?.1】類私有成員的定義和訪問#include<iostream.h>classPerson { //Person類的三個(gè)私有成員 charname[10];//姓名 private: intage; //年齡 charsex; //性別}; main() { PersonP1; P1.age=20; //非法 cout<<P1.name<<endl; //非法 return0; }2.public類成員

一個(gè)類中的公有(public)成員(包括數(shù)據(jù)成員和成員函數(shù))可以被程序中任何代碼(包括函數(shù))訪問,一般情況下,應(yīng)盡量將類的數(shù)據(jù)成員聲明為私有(private),然后為需要被類外部訪問的數(shù)據(jù)成員提供公有的成員函數(shù),實(shí)現(xiàn)對(duì)私有成員的設(shè)置和訪問,這種結(jié)構(gòu)能夠向類的客戶很好的隱藏實(shí)現(xiàn)方法,在有效減少錯(cuò)誤的同時(shí),可以增強(qiáng)程序的可修改性。3.protected類成員使用protected聲明的稱為保護(hù)成員。任何一個(gè)類的保護(hù)成員僅可以被其自己和派生類的所有非靜態(tài)成員函數(shù)和友元函數(shù)直接訪問,也就是說其他的外部函數(shù)是不能訪問它的。因此,對(duì)于那些既要對(duì)外界隱藏,又要能被派生類訪問的成員,可以將它們聲明為保護(hù)成員。

如果基類聲明了私有成員,那么任何派生類都是不能訪問它們的,若希望在派生類中能訪問它們,應(yīng)當(dāng)把它們聲明為保護(hù)成員。如果在一個(gè)類中聲明了保護(hù)成員,就意味著該類可能要用作基類,在它的派生類中會(huì)訪問這些成員。8.2.3三種派生方式的定義

1.私有(private)派生

在聲明一個(gè)派生類時(shí)將派生方式指定為private的,稱為私有派生,用私有派生方式建立的派生類稱為私有派生類,其基類稱為私有基類。由私有派生得到的派生類,它從基類繼承的成員都將變?yōu)樗接谐蓡T,也就是說通過私有派生,派生類從基類繼承來的公有成員和保護(hù)成員都將變成派生類的私有成員,這些成員將只能被派生類的成員函數(shù)和友元函數(shù)訪問。需要重點(diǎn)說明的是,基類的私有成員經(jīng)過私有派生后繼續(xù)保持其基類的私有成員身份,無法被派生類訪問。

2.保護(hù)(protected)派生由保護(hù)派生得到的派生類,它從基類繼承的公有和保護(hù)成員都將變?yōu)榕缮惖谋Wo(hù)成員?;惖乃接谐蓡T經(jīng)過保護(hù)派生后繼續(xù)保持其基類的私有成員身份,依然無法被派生類訪問。保護(hù)派生的特點(diǎn)是:基類的公用成員和保護(hù)成員在派生類中都成了保護(hù)成員,其私有成員仍為基類私有。也就是把基類原有的公用成員也保護(hù)起來,不讓類外任意訪問。3.公有(public)派生由公有派生得到的派生類,它從基類繼承的成員都將維持原有訪問控制特征,即通過公有派生后,派生類從基類繼承的公有成員在派生類中仍然是公有成員,保護(hù)成員仍然是保護(hù)成員,而基類的私有成員經(jīng)過公有派生后繼續(xù)保持其基類的私有成員身份,依然無法被派生類訪問。8.2.4派生類成員訪問控制規(guī)則

1.派生類中新增成員的訪問控制遵循類成員訪問控制的規(guī)則。存取說明符訪問控制規(guī)則Private此派生類的非靜態(tài)成員函數(shù)和友元函數(shù)可以直接訪問Protected此派生類和其子類非靜態(tài)成員函數(shù)和友元函數(shù)可以訪問Public任何非靜態(tài)成員函數(shù),友元函數(shù)和非成員函數(shù)都可以直接訪問2.類成員在派生類中的訪問控制規(guī)則基類成員的存取說明符派生方式public派生protected派生private派生Private在派生類中被隱藏在派生類中被隱藏在派生類中被隱藏Protected派生類中為protected派生類中為protected派生類中為privatePublic派生類中為public派生類中為protected派生類中為private注意:不管是何種派生,基類的private成員永遠(yuǎn)都不能被其派生類直接訪問,但可以通過基類的public和protected成員函數(shù)訪問。

8.3派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)8.3.1派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)的聲明類的構(gòu)造函數(shù)是類的一種特殊的成員函數(shù),它的作用主要是為對(duì)象分配內(nèi)存、進(jìn)行初始化;而析構(gòu)函數(shù)它的作用與構(gòu)造函數(shù)相反。派生類的構(gòu)造函數(shù)聲明格式如下:派生類的構(gòu)造函數(shù)名稱(參數(shù)表):基類的構(gòu)造函數(shù)名(參數(shù)表){ //… //派生類構(gòu)造函數(shù)體}classPoint{intx,y; public: Point(inta,intb) //基類的構(gòu)造函數(shù) { x=a; y=b; cout<<”ConstructingPointclass\n”; } ~Point() //基類的析構(gòu)函數(shù) { cout<<”DestructingPointclass\n”;}};classCircle:publicPoint{ doubleradius; public: Circle(doubler,inta,intb):Point(a,b)//派生類的構(gòu)造函數(shù) { radius=r; cout<<”ConstructingCircleclass\n”; } ~Circle() //派生類的析構(gòu)函數(shù) { cout<<”DestructingCircleclass\n”; }};派生類中含有對(duì)象成員時(shí),其構(gòu)造函數(shù)的聲明格式如下:

派生類的構(gòu)造函數(shù)名稱(參數(shù)表):基類的構(gòu)造函數(shù)名(參數(shù)表),對(duì)象成員名1(參數(shù)表),…對(duì)象成員名N(參數(shù)表){ //… //派生類構(gòu)造函數(shù)體}classCircle2:publicPoint{ doubleradius; PointP1; public:Circle2(doubler,inta,intb):Point(a,b),P1(a,b) //派生類的構(gòu)造函數(shù),定義時(shí)//指定了基類的構(gòu)造函數(shù)和對(duì)象成員P1的構(gòu)造函數(shù) { radius=r; cout<<”ConstructingCircle2class\n”; } ~Circle2() //派生類的析構(gòu)函數(shù) { cout<<”DestructingCircle2class\n”; }};8.3.2派生類的構(gòu)造函數(shù)和析構(gòu)函數(shù)的構(gòu)造規(guī)則

1.基類具有顯式的構(gòu)造函數(shù)時(shí)(1)基類具有不帶參數(shù)的構(gòu)造函數(shù)派生類既可以自己不定義構(gòu)造函數(shù),也可以根據(jù)需要定義自己的構(gòu)造函數(shù),構(gòu)造函數(shù)可以帶參數(shù)也可以省略,在派生類中定義構(gòu)造函數(shù)時(shí)還可省略“:基類構(gòu)造函數(shù)名(參數(shù)表)”。(2)基類僅有帶參數(shù)的構(gòu)造函數(shù)派生類必須顯式的定義其構(gòu)造函數(shù),并在聲明時(shí)指定其基類的某一構(gòu)造函數(shù)和參數(shù)表,把參數(shù)傳遞給基類構(gòu)造函數(shù)。2.基類具有隱式的構(gòu)造函數(shù)時(shí)當(dāng)基類沒有顯式的定義(即隱式的定義)構(gòu)造函數(shù)時(shí),派生類可以根據(jù)需要定義自己的構(gòu)造函數(shù),派生類構(gòu)造函數(shù)的參數(shù)表、基類的構(gòu)造函數(shù)名和參數(shù)表都可以根據(jù)需要省略。8.3.3派生類構(gòu)造函數(shù)和析構(gòu)函數(shù)的調(diào)用順序1.構(gòu)造函數(shù)的調(diào)用順序派生類對(duì)象創(chuàng)建的時(shí)候,構(gòu)造函數(shù)的執(zhí)行順序?yàn)椋海?)基類的構(gòu)造函數(shù)(2)對(duì)象成員的構(gòu)造函數(shù)(3)派生類自身的構(gòu)造函數(shù)2.析構(gòu)函數(shù)的調(diào)用順序與構(gòu)造函數(shù)的調(diào)用順序正好相反。即

(1)派生類自身的析構(gòu)函數(shù)(2)對(duì)象成員的構(gòu)造函數(shù)(3)基類的析構(gòu)函數(shù)【例8.6】派生類Circle2的構(gòu)造函數(shù)和析構(gòu)函數(shù)的執(zhí)行順序//…Point和Circle2類的定義main(){ Circle2C1(0.0,1,1); cout<<”-------------programline----------------\n”; return0;}8.4多重繼承8.4.1多重繼承的聲明前面討論的是單繼承,即一個(gè)類是從一個(gè)基類派生而來的。在C++中還允許從多個(gè)基類中派生出新的子類,這種派生方法稱為多重繼承(或多基派生)。這一強(qiáng)大的派生功能可以大大提高軟件重用的靈活性。聲明的格式如下:class派生類名:派生存取說明符(可省)1基類名1,…,派生存取說明符N基類名N{ //派生類新增的數(shù)據(jù)成員和成員函數(shù)};【例8.7】多重繼承的聲明#include<iostream.h>classCircle1//基類Circle1{protected:intr;public:voidsetx(intx){r=x;}voiddraw(){ cout<<"drawing…\n";}};classCircle2//基類Circle2{protected:intr;public:voidsetx(intx){r=x;}voidwrite(){ cout<<"writing…\n";}};classCircle:publicCircle1,publicCircle2//類Circle公有繼承了Circle1和Circle2{public:voidshow(){ cout<<"showing…\n";}};voidmain(){Circlecc;cc.draw();cc.write();cc.show();}8.4.2多重繼承的幾點(diǎn)說明1.在多重繼承中派生類成員的訪問控制規(guī)則與單一繼承規(guī)則相同。2.多重繼承的構(gòu)造函數(shù)與析構(gòu)函數(shù)定義與單一繼承相似,只是在構(gòu)造函數(shù)定義時(shí)N個(gè)基類的構(gòu)造函數(shù)之間用逗號(hào)分隔。3.多重繼承雖然功能強(qiáng)大,但也容易造成系統(tǒng)的復(fù)雜性,設(shè)計(jì)時(shí)務(wù)必正確和謹(jǐn)慎,能用單一繼承時(shí)盡量不用多重繼承。4.多重繼承容易產(chǎn)生模糊性,在引用時(shí)要注意例如前面例8.7如果按照下面來引用:voidmain(){Circlecc;cc.setx(10);//Circle1的setx還是Circle2的setx?}

voidmain(){Circlecc;cc.Circle1::setx(10);//說明是Circle1中的r為10}8.4.3虛基類

1.虛基類的概念當(dāng)在多條繼承路徑上有一個(gè)公共的基類,在這些路徑中的某幾條匯合處,這個(gè)公共的基類就會(huì)產(chǎn)生多個(gè)實(shí)例(或多個(gè)副本),若只想保存這個(gè)基類的一個(gè)實(shí)例,可以將這個(gè)公共基類說明為虛基類.

2.虛基類的聲明class派生類名:virtual派生存取說明符(可省)虛基類名{ //派生類新增的數(shù)據(jù)成員和成員函數(shù)};3.虛基類的初始化虛基類初始化時(shí),構(gòu)造函數(shù)的調(diào)用順序規(guī)則:(1)同一層派生中包含多個(gè)虛基類時(shí),虛基類的構(gòu)造函數(shù)按它們派生時(shí)聲明的先后次序調(diào)用。(2)如某虛基類是由實(shí)基類派生而來,則先調(diào)用此實(shí)基類的構(gòu)造函數(shù),再調(diào)用虛基類的構(gòu)造函數(shù),最后才是派生類的構(gòu)造函數(shù)。(3)若同一層派生中,同時(shí)存在虛基類與實(shí)基類,應(yīng)先調(diào)用虛基類的構(gòu)造函數(shù),再調(diào)用實(shí)基類的構(gòu)造函數(shù),最后調(diào)用派生類的構(gòu)造函數(shù)。4.虛基類的作用虛基類的作用就是為其他類提供一個(gè)合適的基類,以便派生類可以從它那里繼承和實(shí)現(xiàn)所需的接口。在多重繼承時(shí),當(dāng)派生類的多個(gè)基類有一個(gè)共同的基類時(shí),為防止產(chǎn)生二義性問題可使用虛基類方法。注意:虛基類并不是在聲明基類時(shí)聲明的,而是在聲明派生類時(shí),指定繼承方式時(shí)聲明的。因?yàn)橐粋€(gè)基類可以在生成一個(gè)派生類時(shí)作為虛基類,而在生成另一個(gè)派生類時(shí)不作為虛基類。【例8.11】存在二義性的虛基類多重派生#include<iostream.h>classBase //基類{ protected: intb;public:Base() {b=1;cout<<”ConstructingBaseclass”<<endl; }};classBase1:publicBase//基類1從Base派生{ public:Base1() {cout<<”ConstructingBase1class”<<endl;cout<<”Baseb=”<<b<<endl; }};classBase2:publicBase //基類2從Base派生{ public:Base2() {cout<<”ConstructingBase2class”<<endl;cout<<”Baseb=”<<b<<endl; }};classDerived:publicBase1,Base2//從兩個(gè)基類base1和base2多重派生出子類{ public:Derived() { cout<<”ConstructingDerivedclass”<<endl;cout<<”Baseb=”<<b<<endl; }};main(){ DerivedD1; return0;}改成如下語句:classBas

溫馨提示

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

評(píng)論

0/150

提交評(píng)論