基于C++與虛函數(shù)的多態(tài)性編程實現(xiàn)機制探討_第1頁
基于C++與虛函數(shù)的多態(tài)性編程實現(xiàn)機制探討_第2頁
基于C++與虛函數(shù)的多態(tài)性編程實現(xiàn)機制探討_第3頁
基于C++與虛函數(shù)的多態(tài)性編程實現(xiàn)機制探討_第4頁
基于C++與虛函數(shù)的多態(tài)性編程實現(xiàn)機制探討_第5頁
已閱讀5頁,還剩3頁未讀 繼續(xù)免費閱讀

下載本文檔

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

文檔簡介

1、文章來源 畢業(yè)論文網(wǎng) 基于c+與虛函數(shù)的多態(tài)性編程實現(xiàn)機制探討文章來源 畢業(yè)論文網(wǎng)  以下是yjbys求職網(wǎng)與您分享的一篇關(guān)于基于c+與虛函數(shù)的多態(tài)性編程實現(xiàn)機制探討的計算機應(yīng)用畢業(yè)論文,歡迎瀏覽! 關(guān)鍵詞: 動態(tài)聯(lián)編;虛函數(shù);多態(tài)性 摘要: 關(guān)于虛函數(shù)能否解決類的派生過程中出現(xiàn)的切片問題,論文結(jié)合具體實例,給出了在c+中利用虛函數(shù)實現(xiàn)程序多態(tài)性的設(shè)計方法,并進(jìn)一步探討了多態(tài)性編程的實現(xiàn)機制。 中圖分類號: tp311  文獻(xiàn)標(biāo)識碼:a   文章編號:1004-633x(2011)12-0061-02 多態(tài)性是面象對象程序設(shè)

2、計的重要特征,封裝性、繼承性和多態(tài)性一起并稱為oop(object oriented programming)的三大特征,多態(tài)性是面象對象編程技術(shù)的核心組件之一。多態(tài)性對于c+的學(xué)習(xí)者來說是學(xué)習(xí)過程中最困難的概念,也是理解oop的轉(zhuǎn)折點1。本文基于具體案例,給出了在c+中利用虛函數(shù)實現(xiàn)面向?qū)ο缶幊痰亩鄳B(tài)性的設(shè)計方法,并進(jìn)一步探討了多態(tài)性編程的實現(xiàn)機制。 1 多態(tài)性與虛函數(shù) 多態(tài)性是指為一個函數(shù)名關(guān)聯(lián)多種含義的能力,即同一種調(diào)用方式可以映像到不同的函數(shù)。這種把函數(shù)的調(diào)用與適當(dāng)?shù)暮瘮?shù)體對應(yīng)的活動又稱為綁定(binding)。根據(jù)綁定所進(jìn)行階段的不同,可分為早期綁定(early

3、binding)、晚期綁定(late binding),早期綁定發(fā)生在程序的編譯階段,稱為靜態(tài)聯(lián)編(static binding),晚期綁定發(fā)生在程序的運行階段,稱為動態(tài)聯(lián)編(dynamic binding)。c+支持基于靜態(tài)聯(lián)編和動態(tài)聯(lián)編的兩種不同的多態(tài)性:編譯時的多態(tài)性和運行時的多態(tài)性。 1.1 編譯期多態(tài) 編譯期多態(tài)在oop中的具體體現(xiàn)是函數(shù)重載(overloading),函數(shù)重載指的是允許多個不同函數(shù)使用同一個函數(shù)名,但要求這些同名函數(shù)具有不同的參數(shù)表(當(dāng)然,函數(shù)體的代碼也不同):參數(shù)表中的參數(shù)個數(shù)不同、參數(shù)表中對應(yīng)的參數(shù)類型不同或參數(shù)表中不同類型參數(shù)的次序不同。&

4、nbsp;系統(tǒng)對函數(shù)重載這種多態(tài)性的分辨與處理是在編譯階段完成的。因為重載函數(shù)的形參表是不同的,因些,在編譯過程中,系統(tǒng)就可以根據(jù)函數(shù)調(diào)用時的實參類型來匹配這些同名的函數(shù),進(jìn)而確定函數(shù)調(diào)用語句實際上對應(yīng)的函數(shù)體代碼(位置),故稱這種多態(tài)性是編譯期多態(tài)。 1.2 運行期多態(tài) 通過動態(tài)聯(lián)編技術(shù),為一個函數(shù)名關(guān)聯(lián)多種含義的能力,稱為運行期多態(tài)性。 為增強多態(tài)性,c+不僅支持函數(shù)的重載,還允許在不同的類中出現(xiàn)其原型完全相同的函數(shù),即所謂的超載。函數(shù)超載(overriding) 是指在基類與其派生類的范圍內(nèi),允許多個不同函數(shù)使用完全相同的函數(shù)名、函數(shù)參數(shù)表和函數(shù)返回類型。函

5、數(shù)的超載在更高的層次上充分體現(xiàn)了程序的多態(tài)性。由于函數(shù)超載允許不同的函數(shù)具有完全相同的函數(shù)原型,因此在編譯階段無法判別此次調(diào)用應(yīng)執(zhí)行哪段函數(shù)代碼。只有到了運行過程執(zhí)行到此處時,本文來自論文之家:,轉(zhuǎn)載請保留此標(biāo)記才有可能臨時判別執(zhí)行哪一段函數(shù)代碼,即動態(tài)聯(lián)編。函數(shù)的超載需要動態(tài)聯(lián)編技術(shù)的支持,而動態(tài)聯(lián)編是通過虛函數(shù)來實現(xiàn)的。 1.3虛函數(shù)(virtual function) 在定義某一基類(或其派生類)時,若將其中的某一個非靜態(tài)成員函數(shù)的屬性說明為virtual,則稱該函數(shù)為虛函數(shù)。 虛函數(shù)的使用與函數(shù)超載密切相關(guān)2。第一,基類中某函數(shù)被說明為虛函數(shù);第二,其派生

6、類中又用到與該函數(shù)同一接口,但函數(shù)體不同的超載函數(shù)。二者齊備,當(dāng)編譯到對此函數(shù)的調(diào)用時,相當(dāng)于告訴編譯器:“不用綁定與此函數(shù)名對應(yīng)的具體的函數(shù)代碼段,等到運行時再從具體對象實例中確定它的具體實現(xiàn)。”3這種技術(shù)即晚期綁定技術(shù),這種技術(shù)使得運行期對一個虛函數(shù)的調(diào)用隨著對象實例的變化可以呈現(xiàn)多種結(jié)果,即程序呈現(xiàn)運行期的多態(tài)性。虛函數(shù)是這種運行期多態(tài)性得以實現(xiàn)的必要條件,函數(shù)超載是多態(tài)性的意義所在。 2 利用虛函數(shù)實現(xiàn)程序的多態(tài)性 有了虛函數(shù)的支持就一定能實現(xiàn)動態(tài)聯(lián)編,在程序運行中呈現(xiàn)多態(tài)性嗎?在程序設(shè)計中要采用什么方法才能利用動態(tài)聯(lián)編技術(shù),體現(xiàn)程序的多態(tài)性

7、呢?下面分三種情況討論。 (1)虛函數(shù)并不是程序多態(tài)的充分條件。下面程序1中類的成員函數(shù)雖聲明為虛函數(shù),但仍發(fā)生了切片問題3。 程序1 #include<iostream> #include<string> using namespace std; class pet public: string name; virtual void print();  class dog:public pet public: string breed;&n

8、bsp;virtual void print();  void main()  pet pet_object;  dog dog_object; dog_="珍妮" dog_object.breed="great dane" pet_object =dog_object; pet_object.print();/切片問題,  void pet:print() cout<<"寵物名字:"<

9、<name<<endl; void dog:print() cout<<"寵物名字:"<<name<<endl; cout<<"寵物品種:"<<breed<<endl;  雖然程序中將一個派生類寵物狗對象dog_object賦給了一個基類寵物對象pet_object,但調(diào)用虛函數(shù)print()時,并沒有隨著對象實例的變化而呈現(xiàn)多態(tài)現(xiàn)象,從而去綁定派生類對象的虛函數(shù)。程序的運行結(jié)果是:“寵物名字:珍妮&rd

10、quo;,沒有輸出派生類寵物狗對象dog_object所有的屬性值,而是切去了派生類新增部分的屬性,出現(xiàn)了切片問題。 (2)在程序設(shè)計中,將類及其派生類重載的成員函數(shù)聲明為虛函數(shù),再利用派生類對象初始化基類對象的引用,能實現(xiàn)程序的多態(tài)性,即: baseclass& base_object= derived_object 如程序2所示,銀行允許開設(shè)多種不同的帳戶,下面程序2中為基本銀行帳戶定義了一個基類bankaccount,又定義了兩個派生類marketaccount和 cdaccount,分別代表具有不同取款規(guī)則的帳戶,在每個類中都重載了取款成員函數(shù)wi

11、thdraw(),以適用于所有不同取款規(guī)則的帳戶。轉(zhuǎn)帳操作應(yīng)在所用對象之間進(jìn)行,在完成轉(zhuǎn)帳操作的成員函數(shù)convert()實現(xiàn)代碼中,取款成員函數(shù)withdraw()應(yīng)隨著實例對象(取款帳戶)other的變化而分別綁定不同類的重載的函數(shù)段,則對于重載的成員函數(shù)withdraw()必須采用動態(tài)聯(lián)編的方式進(jìn)行綁定,為此在下面程序中做了這樣的設(shè)計:聲明withdraw()為虛函數(shù); 將轉(zhuǎn)帳函數(shù)convert()的形參設(shè)計成基類對象的引用bankaccount&,當(dāng)轉(zhuǎn)帳函數(shù)以不同的帳戶對象(特別是派生類對象)被調(diào)用時,實際上是用派生類對象初始化了基類對象的引用。程序運行測試結(jié)果達(dá)到了預(yù)期的目的

12、,當(dāng)然,程序中略去了所有其它與本文討論無關(guān)的成員函數(shù)及實現(xiàn)的細(xì)節(jié),將存款函數(shù)聲明為虛函數(shù)也不是必須的,這是為了下節(jié)說明的方便。 程序2 #include<iostream> #include<cstring> using namespace std; class bankaccount  char name80; double balance; public: bankaccount(char ,double); virtual void deposit(double amount

13、); virtual bool withdraw(double); void convert(bankaccount&,int );  class marketaccount :public bankaccount   int withdraw_numbers; public: marketaccount(char ,double); virtual bool withdraw(double )  class cdaccount:public bankaccount&

14、nbsp; double interest_rate; public: cdaccount(char ,double,double); virtual bool withdraw(double );  bool bankaccount :withdraw(double amount)  balance-=amount; return 1;  bool  cdaccount :withdraw(double amount) cout<<"提前取款,罰利息的25%n&

15、quot; double temp=amount+get_balance() *interest_rate/100; balance-=temp; return 1;  bool marketaccount :withdraw(double amount)  cout<<"取款交手續(xù)費1.5n; balance-=amount+1.5; return 1;  /將other帳戶的錢轉(zhuǎn)至當(dāng)前帳戶 void bankaccount:convert (bank

16、account& other,int amount)  other.withdraw(amount) deposit(amount);  / ……(略去其余函數(shù)的實現(xiàn)部分) void main()  cdaccount zhang ("張華",1000,3); marketaccount wang ("王芳",300); wang.convert(zhang ,500);  (3)程序設(shè)計中,將類及其派生類重載的成員函數(shù)

17、聲明為虛函數(shù),利用指向基類和派生類指針的賦值兼容性,實現(xiàn)程序的多態(tài)性,即: baseclass * base_object _point=&derived_object 真對上述程序2,只須將轉(zhuǎn)帳函數(shù)的參數(shù)類型改為指向基類對象的指針,并作如下調(diào)整: void bankaccount:convert (bankaccount* other,int amount)  other->withdraw(amount) deposit(amount);  對函數(shù)調(diào)用時的實參對象要采用對象地址的格式。 

18、在以樹形為主要結(jié)構(gòu)的類的派生關(guān)系中,虛函數(shù)是架構(gòu)程序模塊的主要方式,虛函數(shù)在基類中對某種操作提供一個框架,在派生類中為框架提供不同的實現(xiàn),虛函數(shù)的語義決定了只有當(dāng)用父類指針訪問它們時,才能實現(xiàn)運行時的多態(tài)性4,從而解決切片問題。 3 虛函數(shù)的實現(xiàn)機制 c+中的虛函數(shù)是實現(xiàn)面向?qū)ο蟪绦蛟O(shè)計最重要的語言機制,是動態(tài)聯(lián)編技術(shù)實現(xiàn)程序多態(tài)性的基石。但是程序執(zhí)行的時候,代碼已經(jīng)脫離編譯器、鏈接器的干預(yù),那么是誰完成執(zhí)行時的動態(tài)聯(lián)編?背后的技術(shù)是什么? 實際上編譯器在程序靜態(tài)編譯期已經(jīng)做好了必要的準(zhǔn)備:它為每一個包含了虛函數(shù)的類產(chǎn)生一個虛擬函數(shù)表vtab,為該類的所有對象共享

19、;為類的每一個實例對象添加一個指針分量vptr,該指針指向所屬類的虛函數(shù)表vtab5。 虛函數(shù)表vtab中的每一項是一個虛函數(shù)地址,類中的每一個虛函數(shù)都在表中確切的占有一項。程序2中派生類對象cdaccount:zhang的內(nèi)存部局和類的虛函數(shù)表如圖1所示。 在圖1中注意到,編譯器會把指向虛函數(shù)表的指針存放于對象實例最前面的位置,這保證運行時我們可以通過對象實例的地址得到這張?zhí)摵瘮?shù)表,然后就可以遍歷其中的函數(shù)指針,并調(diào)用相應(yīng)的虛函數(shù)。在程序2的主函數(shù)中增加如下代碼: typedef void(*fun)(void); fun pfun=null; /由對象zhang的地址得到對象頭部的指針分量 cout<<(int*)(&zhang)<<endl; /取得虛函數(shù)表vtab的地址 cout<<(int*)*(int*)(&zhang)<<endl;

溫馨提示

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

評論

0/150

提交評論