關(guān)于繼承多態(tài)及動(dòng)態(tài)綁定_第1頁
關(guān)于繼承多態(tài)及動(dòng)態(tài)綁定_第2頁
關(guān)于繼承多態(tài)及動(dòng)態(tài)綁定_第3頁
關(guān)于繼承多態(tài)及動(dòng)態(tài)綁定_第4頁
關(guān)于繼承多態(tài)及動(dòng)態(tài)綁定_第5頁
全文預(yù)覽已結(jié)束

下載本文檔

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

文檔簡介

1、最近在看 c+primer ,學(xué)習(xí)到繼承的時(shí)候碰到了一些問題,現(xiàn)整理如下:繼承:派生類繼承了其基類的數(shù)據(jù)成員和成員函數(shù),并且可以直接使用他們,就好像他們是派生類的成員一樣。繼承機(jī)制具有兩種特殊的性質(zhì):多態(tài)和動(dòng)態(tài)綁定q:什么是多態(tài)a:當(dāng)我們在c+中說到多態(tài)時(shí),主要是指基類的指針/引用可以指向其任意派生類的能力。eg class a ; class aa:public a ; class aaa:public a ; void eval(const a* a ) a-test(); /test 是個(gè)虛函數(shù)并且在各個(gè)派生類中都是實(shí)現(xiàn)了的 若: aa aa;aaa *aaa = new aaa;eva

2、l(&aa) ;eval(aaa) ; 則:在上例中調(diào)用eval 的時(shí)候,傳的是派生類的地址,在編譯時(shí)編譯器會(huì)將其轉(zhuǎn)為基類的。那在調(diào)用test的時(shí)候調(diào)用的是誰的test()實(shí)例呢?答:調(diào)用的是派生類的。上例,在eval 函數(shù)中,根據(jù)a 指向的實(shí)際類對象來調(diào)用test 的虛擬成員函數(shù)。在程序執(zhí)行的每個(gè)調(diào)用點(diǎn)上,a 所指向的真正類型才確定下來,并調(diào)用適當(dāng)?shù)膖est()實(shí)例。這依賴于動(dòng)態(tài)綁定機(jī)制。q:什么是動(dòng)態(tài)綁定?a:想要了解動(dòng)態(tài)綁定首先要了解虛函數(shù)表。虛函數(shù)(virtual function ) 是通過一張?zhí)摵瘮?shù)表 (virtual table ) 來實(shí)現(xiàn)的。 簡稱為 v-table。在

3、這個(gè)表中,主是要一個(gè)類的虛函數(shù)的地址表,這張表解決了繼承、覆蓋的問題,保證其容真實(shí)反應(yīng)實(shí)際的函數(shù)。 這樣,在有虛函數(shù)的類的實(shí)例中這個(gè)表被分配在了這個(gè)實(shí)例的內(nèi)存中,所以, 當(dāng)我們用父類的指針來操作一個(gè)子類的時(shí)候,這張?zhí)摵瘮?shù)表就顯得由為重要了,它就像一個(gè)地圖一樣,指明了實(shí)際所應(yīng)該調(diào)用的函數(shù)。在 c+的標(biāo)準(zhǔn)規(guī)格說明書中說到,編譯器必需要保證虛函數(shù)表的指針存在于對象實(shí)例中最前面的位置(這是為了保證正確取到虛函數(shù)的偏移量)。假設(shè)我們有這樣的一個(gè)類:class base public :virtual void f() cout base:f endl; virtual void g() cout bas

4、e:g endl; virtual void h() cout base:h endl; ;若有:base b; 則 b 的內(nèi)存如下:如圖所示, 對象的內(nèi)存的第一個(gè)位置存放的是虛函數(shù)表的地址,對象的虛函數(shù)按照聲明的順序依次排列在虛函數(shù)表中。虛函數(shù)表的最后一位是一個(gè)結(jié)束符(結(jié)束符根據(jù)不同的編譯器而不同) ,標(biāo)示著虛函數(shù)表的結(jié)束。單繼承(無虛函數(shù)覆蓋)下的虛函數(shù)表:如果現(xiàn)在有這樣一個(gè)類:classderive: public base public :virtual void f1() cout base:f1 endl; virtual void g1() cout base:g1 endl;

5、virtual void h1() cout base:h1 endl; ;類圖如下:在這個(gè)繼承關(guān)系中,子類沒有重載任何父類的函數(shù)。那么,在派生類的實(shí)例中,其虛函數(shù)表如下所示:若有:derive d ;則 d 的虛擬表如下:由圖我們可以看到:1)虛函數(shù)按照其聲明順序放于表中。2)父類的虛函數(shù)在子類的虛函數(shù)前面。單繼承(有虛函數(shù)覆蓋)下的虛函數(shù)表:如果現(xiàn)在有這樣一個(gè)類:classderive: public base public :virtual void f() cout base:f endl; virtual void g1() cout base:g1 endl; virtual vo

6、id h1() cout base:h1 f() ;則 b-f()執(zhí)行的就是derive : :f q:如上例所示b-f()執(zhí)行的就是derive : :f ,那子類其他的元素和方法呢?通過b 可以訪問的到嗎?a:是不可以的。base *b = new derive;這一句的步驟分解如下:1) 定義一個(gè)指向base 的指針 b ,賦初值為null 2) new 出來一塊空間3) 新生成一個(gè)derive 的臨時(shí)對象(動(dòng)態(tài)綁定過程),使用缺省構(gòu)造函數(shù)構(gòu)造4) 將這個(gè)臨時(shí)對象的地址賦給b(賦值時(shí)進(jìn)行類型轉(zhuǎn)換)5) 析構(gòu)并刪除這個(gè)臨時(shí)對象理解方法一 :因?yàn)橛虻年P(guān)系所以訪問不到由于 b 是聲明為base

7、 類型,所以 b 的操作限于base 的域內(nèi),因此那些在派生類derive中的元素和方法是肯定訪問不到的。動(dòng)態(tài)綁定是把derive : :f 的地址覆蓋了base : :f 。理解方法二 :看上例中的對象內(nèi)存圖中的“其他成員”其實(shí)只有數(shù)據(jù)成員,因?yàn)閷ο髢?nèi)存中不存放成員函數(shù)的地址。函數(shù)的地址是在代碼區(qū)域,對象的內(nèi)存中只存放數(shù)據(jù)成員,當(dāng)我們要調(diào)用成員函數(shù)時(shí), 就通過一個(gè)寄存器將函數(shù)操作的對象的首地址(也就是this 指針) 傳遞過去就可以了,傳遞不同的對象指針,就操作不同的數(shù)據(jù)。(這個(gè)成員函數(shù)到底是怎么調(diào)用的呢?)因此,通過b 訪問成員函數(shù)肯定是訪問的自己的,那數(shù)據(jù)成員呢?當(dāng)派生類中有對基類的同名

8、數(shù)據(jù)成員時(shí),通過b 訪問的是誰呢 ?實(shí)踐證明還是base的。 (看內(nèi)存上他們并沒有什么覆蓋 為什么呢? )q:派生類中與基類同名的函數(shù)是重載關(guān)系嗎?a:不是的。重載要求函數(shù)在同一域內(nèi),基類成員雖然可以直接被派生類訪問,但是它的域是在基類,因此,派生類中與基類同名的函數(shù)與基類中的該函數(shù)不是重載關(guān)系。若想讓他們變?yōu)橹剌d關(guān)系怎么做呢?用 using 關(guān)鍵字就ok 啦 eg:class a void he() ; ; class aa: public a void he(int tt=0 ); using a:he; ; q:派生類的構(gòu)造/析構(gòu)是怎樣的?a:構(gòu)造順序:1) 基類的構(gòu)造函數(shù)(按照派生表順序)2) 成員類對象的構(gòu)造函數(shù)(按照成員的聲明順序)3) 派生類自己的構(gòu)造函數(shù)eg:class a a() ;a () ;class aa:public a aa(); aa () ;string strtemp;int ntemp; 若: aa aa;則執(zhí)行順序?yàn)椋?) a() ;2) string 的構(gòu)造; int 的構(gòu)造3) aa () ;析構(gòu)順序:與構(gòu)造順序剛好相反。1)aa ()2)int 的析構(gòu), string 的析構(gòu)3)aa () ;q:什么是靜態(tài)類型?什么

溫馨提示

  • 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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論