




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、團隊學生技術應用交流講座目 錄多態性虛函數與動態綁定純虛函數與抽象類實例講解習題和課后閱讀資料多態性多態性的定義何謂多態性?多態性是指給同樣的接口發送同樣的消息會導致不同的行為。多態意味著一個對象有著多重特征,可以在特定的情況下,表現不同的狀態,從而對應著不同的屬性和方法。 多態性是面向對象程序設計的重要特征之一。假設程序設計語言不支持多態性,不能稱為面向對象的語言。C+多態性C+有哪些多態性機制?函數重載運算符重載虛函數函數重載和運算符重載是編譯時表達出來的多態性,虛函數那么表達了運行時的多態性。虛函數與動態綁定例如:樂器類繼承體系類定義Instrument 樂器Wind 管樂器Woodwi
2、nd 木管樂器Brass 銅管樂器Percussion 打擊樂器Stringed 弦樂器接口說明play 演奏adjust 調整樂器what 顯示樂器信息類型的向上轉換(Upcasting)將派生類地址指針或引用沿著繼承樹向上的方向賦給基類指針(賦值兼容原那么)Upcasting將對象按傳址by address而非傳值(by value)方式進行操作,而多態性需通過Upcasting來表達。我們想做什么?提供給用戶一個通用的不變的系統使用接口函數tune,無論類進行了怎樣的變動,這個接口都能正常可靠地工作(總能按照我們的期望選出正確的樂器演奏)我們想做什么?我們的要求是合理的,這種要求系統具備
3、動態識別能力的需求,在實際運行的很多軟件系統當中都是一項根本要求,這正是要求系統具備多態性。void tune(Instrument& i) i.play(); int main() Wind flute; tune(flute); / Upcasting 先看一個例子#include using namespace std;enum note middleC, Csharp, Eflat ;.class Instrument public: void play(note) const cout Instrument:play endl; ;/ Wind objects are Instrum
4、ents/ because they have the same interface:class Wind : public Instrument public: / Redefine interface function: void play(note) const cout Wind:play endl; ;void tune(Instrument& i) / . i.play(middleC);int main() Wind flute; tune(flute); / Upcasting return 0; 我們定義了Wind對象flute,通過接口tune操作play函數,顯然我們希望
5、flute對象能正確地調用Wind類的play函數運行的結果#include using namespace std;enum note middleC, Csharp, Eflat ;.class Instrument public: void play(note) const cout Instrument:play endl; ;/ Wind objects are Instruments/ because they have the same interface:class Wind : public Instrument public: / Redefine interface fu
6、nction: void play(note) const cout Wind:play endl; ;void tune(Instrument& i) / . i.play(middleC);int main() Wind flute; tune(flute); / Upcasting return 0; 程序卻調用了基類Instrument的play函數,顯然這不是我們希望的結果!問題出在哪兒了呢?改動一下例子#include using namespace std;enum note middleC, Csharp, Eflat ;.class Instrument public: vi
7、rtual void play(note) const cout Instrument:play endl; ;/ Wind objects are Instruments/ because they have the same interface:class Wind : public Instrument public: / Redefine interface function: void play(note) const cout Wind:play endl; ;void tune(Instrument& i) / . i.play(middleC);int main() Wind
8、flute; tune(flute); / Upcasting return 0; 將基類函數play函數定義成為虛函數virtual function初見虛函數虛函數(virtual function)的定義virtual 返回類型 函數名參數表;class Shapeprivate:public:virtual void Draw() cout “Draw a shapeendl; ;派生類中的虛函數虛函數是類成員函數(class member function);在派生類(derived class)中對虛函數的實現重新定義稱之為覆蓋(override)虛函數的“身份在繼承之間能被持續傳
9、遞下去再次運行,結果#include using namespace std;enum note middleC, Csharp, Eflat ;.class Instrument public: virtual void play(note) const cout Instrument:play endl; ;/ Wind objects are Instruments/ because they have the same interface:class Wind : public Instrument public: / Redefine interface function: void
10、 play(note) const cout Wind:play endl; ;void tune(Instrument& i) / . i.play(middleC);int main() Wind flute; tune(flute); / Upcasting return 0; 這次結果是我們希望的結果!我們引入了虛函數機制,導致了這樣的結果。“神奇的 執行方式 ?以基類指針運行虛函數,程序就能執行我們所期望的正確的派生類的函數體,虛函數為什么會有這樣“神奇的運行機制呢?通過繼承而相關的不同類,他們的對象能夠對同一個函數作出不同的響應.這樣“神奇的 多態性是怎樣實現的呢?靜態綁定與動態綁
11、定綁定(binding)程序自身彼此關聯的過程,確定程序中的操作調用與執行該操作的代碼間的關系。靜態綁定(early binding)綁定過程出現在編譯階段,用對象名或者類名來限定要調用的函數。動態綁定(dynamic/later binding)綁定過程工作在程序運行時執行,在程序運行時才確定將要調用的函數。“神奇的 執行方式 動態綁定C+的虛函數在運行時正是通過動態綁定實現多態機制的。動態綁定是如何實現的呢?動態綁定是通過編譯器運用虛函數表VTBL和虛表指針VPTR而實現,在運行時通過動態查詢實現對正確函數體的綁定。VTBL編譯器會為聲明了虛函數的類建立一個虛函數表。VTBL實際上是一個函
12、數指針數組,每個虛函數占用這個數組的一個入口slot。一個類只有一個VTBL,不管它有多少個實例。派生類有自己的VTBL,但是派生類的VTBL與基類的VTBL有相同的函數排列順序,同名的虛函數被放在兩個數組的相同位置上。 VPTR在創立類實例的時候,編譯器還會在每個實例的內存布局中增加一個VPTR指針,該指針指向本類的VTBL。 最后,是動態聯編在調用此類的構造函數時,在類的構造函數中,編譯器會隱含執行VPTR與VTBL的關聯代碼,將VPTR指向對應的VTBL。這就將類與此類的VTBL聯系了起來。在調用類的構造函數時,指向基類的指針此時已經變成指向具體的類的this指針,依靠此this指針,進
13、一步得到正確的VPTR,即可得到正確的VTBL,從而實現了多態性。在此時才能真正與函數體進行連接,這就是動態聯編。一個更大的例子#include using namespace std; enum note middleC, Csharp, Cflat ; / Etc. class Instrument public: virtual void play(note) const cout Instrument:play endl; virtual char* what() const return Instrument; virtual void adjust(int) ; class Win
14、d : public Instrument public: void play(note) const cout Wind:play endl; char* what() const return Wind; void adjust(int) ; class Percussion : public Instrument public: void play(note) const cout Percussion:play endl; char* what() const return Percussion; void adjust(int) ; class Stringed : public I
15、nstrument public: void play(note) const cout Stringed:play endl; char* what() const return Stringed; void adjust(int) ; 一個更大的例子class Brass : public Wind public: void play(note) const cout Brass:play endl; char* what() const return Brass; ; class Woodwind : public Wind public: void play(note) const c
16、out Woodwind:play endl; char* what() const return Woodwind; ; void tune(Instrument& i) i.play(middleC); void f(Instrument& i) i.adjust(1); / Upcasting during array initialization: Instrument* A = new Wind, new Percussion, new Stringed, new Brass, ; 一個更大的例子int main() Wind flute; Percussion drum; Stri
17、nged violin; Brass flugelhorn; Woodwind recorder; tune(flute); tune(drum); tune(violin); tune(flugelhorn); tune(recorder); f(flugelhorn); /: f(flugelhorn)函數調用的是哪個版本的adjust()函數呢?虛函數的特點實現動態多態性時,必須使用基類類型的指針pointer或引用(reference)型變量,通過該變量引用虛函數,才能實現動態的多態性。只有類的成員函數才能說明為虛函數。這是因為虛函數僅適用于有繼承關系的類對象。靜態static成員函數
18、,為所有同一類對象共有,不受限于某個對象,不能作為虛函數。虛函數的特點派生類中定義虛函數必須與基類中的虛函數同名外,還必須同參數表,同返回類型。否那么被認為是重載(overload),而不是虛函數。 如果定義放在類外,virtual只能加在函數聲明前面,不能再加在函數定義前面。虛函數的特點析構函數可定義為虛函數,構造函數不能定義虛函數,因為在構造函數時對象還沒有完成實例化。在基類中及其派生類中都動態分配的內存空間時,必須把析構函數定義為虛函數,實現撤消對象時的多態性。采用了虛函數函數執行速度要稍慢一些。為了實現多態性,每一個派生類中均要保存相應虛函數的入口地址表,函數的調用機制也是間接實現。所
19、以多態性總是要付出一定代價,但通用性是一個更高的目標。純虛函數與抽象類純虛函數(pure vitual function) 純虛函數是指被標明為不具體實現的虛擬成員函數。它用于這樣的情況:定義一個基類時,會遇到無法定義基類中虛函數的具體實現,其實現依賴于不同的派生類。 定義純虛函數的一般格式為:virtual 返回類型 函數名參數表=0;定義純虛函數須注意 定義純虛函數時,不能定義虛函數的實現局部。即使是函數體為空也不可以,函數體為空就可以執行,只是什么也不做就返回。而純虛函數不能調用。 在派生類中必須有重新定義的純虛函數的函數體,這樣的派生類才能用來定義對象。抽象類(abstract class)的定義 含有純虛函數的基類是不能用來定義對象的。純虛函數沒有實現局部,不能產生對象,所以含有純虛函數的類是抽象類。引入抽象類有何意義?1 基類的操作表達一種抽象的行為概念,而非能具體化的實體,不必也不能將基類對象實例化,因此使基類成為抽象類,讓它表達一種表征共性的概念,而由派生類具體實現純虛函數表達的概念。2 抽象類的純虛函數表達了一種“規約和“協議的含義,只有接口的約定,沒有實現的約束,這樣就使接口與實現完成解耦,便于軟件統一接口的同時保持實現的靈活性,這也正是組件編程的根本思想。抽象類的使用要求 抽象類不能實例化 抽象
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 安全用氣手冊3篇
- 出租車買賣條件3篇
- 工程代理人職責說明3篇
- 雙方項目合作協議3篇
- 2025學前班班主任工作總結(15篇)
- 托管房屋租賃合同集錦(20篇)
- 高中語文作文教學中高階思維訓練的實證研究與效果分析
- 2024年新疆石河子國有資產經營有限公司崗位選聘考試真題
- 2024年神農架優撫醫院招聘醫療衛生專業技術人員考試真題
- 浙江大學愛丁堡大學聯合學院招聘筆試真題2024
- 項目部施工管理實施計劃編制任務分工表
- 【2021部編版語文】-三年級下冊第七單元教材解讀--PPT課件
- 橙色黑板風小學生知識產權科普PPT模板
- 電網公司變電設備帶電水沖洗作業實施細則
- 中國供銷合作社標識使用手冊課件
- Q∕CR 9218-2015 鐵路隧道監控量測技術規程
- 甲狀腺解剖及正常超聲切面ppt課件
- 上海市城市地下空間建設用地審批及房地產登記試行規定
- 蠕墨鑄鐵項目可行性研究報告寫作范文
- “V”法鑄造工藝及應用
- 高二年級學業水平考試備考實施方案
評論
0/150
提交評論