多型性的概念
多型性(polymorphism)是物件導向程式設計的乙個重要特徵,利用多型性可以設計和實現乙個易於擴充套件的系統.
在c++程式設計中,多型性是指具有不同功能的函式可以用乙個函式名,這樣就可以用乙個函式名呼叫不同內容的函式.
在物件導向方法中一般是這樣表述多型性的:向不同的物件傳送同乙個訊息,不同的物件在接收時會產生不同的行為(即方法)。也就是說,每個物件可以用自己的方式去響應共同的訊息.
從系統實現的角度看,多型性分為兩類:靜態多型性和動態多型性。
以前學過的函式過載和運算子過載實現的多型性屬性靜態多型性,在程式編譯系統就能決定呼叫的是哪個函式,因此靜態多型性又稱為編譯時的多型性。靜態多型性是通過函式的過載實現的(運算子過載實質上也是函式過載)。
動態多型性是程式執行過程中才動態的確定操作所針對的物件。它又稱執行時多型性,動態多型性是通過虛函式(virtual function)實現的。
虛函式虛汗的作用
在類的繼承層次結構中,在不同的層次中可以出現名字相同,引數個數和型別都相同而功能不同的函式。系統根據同名覆蓋的原則決定呼叫的物件。
虛函式的作用是允許在派生類中重新定義域基類同名的函式,並且可以通過基類指標或引用來訪問基類和派生類中的同名函式。
虛函式的使用方法
1)在基類用virtual宣告成員函式為虛函式。這樣就可以在派生類中重新定義此函式,為它賦予新的功能,並能方便的被呼叫,在類外定義虛函式時,不必再加virtual
2)在派生類中重新定義此函式,要求函式名,函式型別,函式引數個數和型別全部與基類的虛函式相同,並根據派生類的需要重新定義函式體。
c++規定,當乙個成員函式被宣告為虛函式後,其派生類中的同名函式都自動成為虛函式,因此在派生類重新宣告該虛函式時,可以加virtual,也可以不加,但是習慣上一般在每一層宣告該函式時都加virtual,使程式更加清晰。
如果在派生類中沒有對基類的虛函式重新定義,則派生類簡單的繼承其直接基類的虛函式。
3)定義乙個指向基類物件的指標變數,並使它指向同一類族中需要呼叫該函式的物件。
4)通過該指標變數呼叫此虛函式,此時呼叫的就是指標變數執行的物件的同名函式。
通過虛函式於指向基類物件的指標變數的配合使用,就能方便的呼叫同一類族中不同類的同名函式,只要先用基類指標指向即可。如果指標不斷的指向同一類族中不同類的物件,就能不斷的呼叫這些物件中的同名函式。
需要說明的是;有時在基類定義的非虛函式會在派生類中被重新定義,如果用基類指標呼叫該成員函式,則系統會呼叫物件中基類部分的成員函式;如果用派生類指標呼叫該成員函式,則系統會呼叫派生類中物件的成員函式,這並不是多型性行為(使用了不同型別的指標),沒有用到虛函式的功能。
以前介紹的函式過載是同一層次上同名函式問題,而虛函式處理的是不同派生層次上的同名函式問題,前者是橫向過載,後者可以理解為縱向過載,但與過載不同的是:同一類族的虛函式的首部是相同的,而函式過載時函式的首部是不同的(引數個數和型別不同)
在宣告情況下應當宣告虛函式
使用虛函式時,有兩點要注意:
1)只能用virtual宣告類的成員函式,使它成為虛函式,而不能將類外的普通函式宣告為虛函式,因為虛函式的作用是允許在派生類中對基類的虛函式重新定義,顯然,它只能用於類的繼承層次結構中。
2)乙個成員函式被宣告為虛函式後,在同一類族中的類就不用再定義乙個非virtual的但與該虛函式具有相同引數(包括個數和型別)和函式返回值型別的同名函式。
需要說明的是:使用虛函式,系統要有一定的空間開銷,當乙個類帶有虛函式時,編譯系統就會為該類構造乙個虛函式表(virtual function table,簡稱vtable),它是乙個指標陣列,存放每個虛函式的入口位址,系統在進行多型關聯時的時間開銷很少的,因此,多型是高效的。
虛析構函式
析構函式的作用是在物件撤銷之前做必要的"清理現場"的工作,當派生類的物件從記憶體中撤銷時一般先呼叫派生類的析構函式,然後再呼叫基類的析構函式。
但是如果用new運算子建立了臨時物件,若基類中有析構函式,並且定義了乙個指向該基類的指標變數,在程式用帶指標引數的delete運算子撤銷物件時,會發生乙個情況,系統會只執行基類的析構函式,而不會指向派生類的析構函式。
當基類的析構函式為虛函式時,無論指標指向的是同一類族中的哪乙個物件,系統會採用動態關聯,呼叫相應的析構函式,對該物件進行清理工作。
如果將基類的析構函式宣告為虛函式,由該基類所派生的所有派生類的析構函式也都自動成為虛函式,即使派生類的析構函式與基類析構函式名字不相同。
最好把基類的析構函式宣告為虛函式,這樣使所有派生類的析構函式都自動成為虛函式,這樣,如果程式中顯示的用delete運算子準備刪除乙個物件,而delete運算子操作的物件用了指向派生類物件的基類指標,則系統會呼叫相應類的析構函式
虛析構函式的概念和用法很簡單,但它在物件導向程式設計中卻是很重要的技巧。專業人員一般都習慣宣告虛析構函式,即使基類並不需要析構函式,也顯示宣告乙個函式體為空的虛析構函式。以保證在撤銷動態分配空間時能得到正確的處理
純虛函式和抽象類
純虛函式
有時在基類中將某一成員函式宣告為虛函式,並不是基類本身的需求,而是考慮到派生類的需要,在基類中預留了乙個函式名,具體功能留給派生類根據需要去定義。
純虛函式是在宣告虛函式時被初始化為0的函式,宣告純虛函式的一般形式為
virtual 函式型別 函式名(引數列表) = 0;
注意:1)純虛函式沒有函式體
2)最後的"=0"並不代表函式的返回值為0,它只起形式上的作用,告訴編譯系統這是純虛函式
3)這是乙個宣告語句,最後應該有分號
純虛函式只有函式名而不具備函式的功能,不能被呼叫,它只是通知編譯系統,在這裡宣告乙個虛函式,留待派生類中定義。
在派生類中提供定義後,它才能具備函式的功能,可被呼叫
純虛函式的作用是在基類中為派生類保留乙個函式的名字,以便派生類根據需要對它進行定義。
如果在基類中沒有保留函式名字,則無法實現多型性。
如果在乙個類中宣告了純虛函式,而在其派生類中沒有對該函式定義,在該虛函式在派生類中仍然為純虛函式。
抽象類如果宣告了乙個類,一般可以用它定義物件,但是在物件導向程式設計中,往往有一些類,他們不用來生成物件,定義這些類的唯一目的是用它作為基類去建立派生類。
這種不用來定義物件而只作為一種基本型別用作繼承的類,稱為抽象類(abstract class),由於它常用作基類。通常成為抽象基類。
凡是包含純虛函式的類都是抽象類,因為純虛函式是不能被呼叫的,保護純虛函式的類是無法建立物件的。抽象類的作用是作為乙個類族的公共基類,或者說為乙個類族提供乙個公共介面.
雖然抽象類不能定義物件(或者說抽象類不能例項化),但是可以可以指向抽象類資料的指標變數。
當派生類成為具體類之後,就可以用這種指標指向派生類物件,然後如果該指標呼叫虛函式,實現多型的操作。
如果在基類宣告了虛函式,則在派生類中凡是與該函式有相同的函式名,函式型別,引數個數和型別的函式,均為虛函式(不論在派生類中是否用virtual宣告)
C 之多型性與虛函式
物件導向程式設計中的多型性是指向不同的物件傳送同乙個訊息,不同物件對應同一訊息產生不同行為。在程式中訊息就是呼叫函式,不同的行為就是指不同的實現方法,即執行不同的函式體。也可以這樣說就是實現了 乙個介面,多種方法 從實現的角度來講,多型可以分為兩類 編譯時的多型性和執行時的多型性。前者是通過靜態聯編...
C 之多型性與虛函式
物件導向程式設計中的多型性是指向不同的物件傳送同乙個訊息,不同物件對應同一訊息產生不同行為。在程式中訊息就是呼叫函式,不同的行為就是指不同的實現方法,即執行不同的函式體。也可以這樣說就是實現了 乙個介面,多種方法 從實現的角度來講,多型可以分為兩類 編譯時的多型性和執行時的多型性。前者是通過靜態聯編...
VC 之 多型性與虛函式
多型性是物件導向程式設計的關鍵技術之一。利用多型性技術,可以呼叫同乙個函式名的函式,實現完全不同的功能。若程式語言不支援多型性,不能稱為物件導向的語言。在c 中有兩種多型性 1 定義格式 虛函式是乙個類的成員函式,定義格式如下 virtual 返回型別 函式名 參數列 說明 2 通過虛函式實現多型性...