一、知識點
1、乙個操作隨著所傳遞的物件型別的不同能夠做出不同的反應,其行為模式成為多型。(p413)
2、基類與派生類的同名操作,只要標記上virtual,則該操作便具有多型性。(p416)
3、一旦標記基類的函式為虛函式,便有連鎖反應,後面繼承的類中一切同名成員函式都變成了虛函式。如果是引發實際複製動作的傳遞,則子類物件完全變成基類物件了,這時候,便不會再有懸念了,即不會有多型了。因為在引數傳遞的過程中已經將物件的性質做了肯定的轉變。而對於確定的物件,是沒有選擇操作可言的。因此說白了,就是僅僅對於物件的指標和引用的間接訪問,才會發生多型現象。(p417)
4、虛函式機理:
(1)、通過預先設定其成員函式的虛函式性質,使得任何**該成員函式的未定型別的物件操作在編譯時,都以乙個不確定的指標特殊地「引命待發」來編碼,到了執行時,遇到確定型別的物件,才突然指定其真正的行為。即滯後到執行時,根據具體型別的物件來**成員函式。
(2)、多型性實現的原理:
當將函式宣告為virtual時,編譯器在編譯的時候,發現類中有虛函式,此時編譯器會為每個包含虛函式的類建立乙個虛表,該表是乙個一維陣列,在這個陣列中存放著每個虛函式的位址。那麼如何確定虛表呢?編譯器還為每個類的物件提供了乙個虛表指標,這個指標指向了物件所屬類的虛表。在程式執行時,根據物件的型別去初始化虛指標,從而讓虛指標正確的指向所屬類的虛表,從而在呼叫虛函式時,能夠找到正確的函式。
在建構函式總,進行了虛表的建立和虛表指標的初始化。在構造子類物件時,要先呼叫父類的建構函式,此時編譯器只「看到了」父類,並不知道後面是否還有繼承者,它初始化父類物件的虛表指標,該虛表指標指向父類的虛表。執行子類的建構函式時,子類物件的虛表指標被初始化,指向自身的虛表。
對於虛函式呼叫來說,每個物件內部都有乙個虛表指標,該虛表指標被初始化為本類的虛表。所以在程式中,不管你的物件型別如何轉換,但該物件內部的虛表指標是固定的,所以才能實現動態的物件函式呼叫,這就是c++多型性實現的原理。
(5)、總結(基類有虛函式):
a、每乙個類都有虛表。
b、虛表可以繼承,如果子類沒有重寫虛函式,那麼子類虛表中仍然會有該函式的位址,只不過這個位址指向的是基類的虛函式實現。如果基類3個虛函式,那麼基類的虛表中就有三項(虛函式位址),派生類也會有虛表,至少有三項,如果重寫了相應的虛函式,那麼虛表中的位址就會改變,指向自身的虛函式實現。如果派生類有自己的虛函式,那麼虛表中就會新增該項。
c、派生類的虛表中虛函式位址的排列順序和基類的虛表中虛函式位址排列順序相同。
6、編譯器看見虛函式呼叫,就要做滯後處理。由於間接訪問比直接訪問繞了乙個彎,於是付出了時間代價和儲存若干指標位址的空間代價。為了在使用類的程式設計中隨時隨地體現多型性,只要是繼承結構,應盡量將成員函式設計成虛函式。
7、虛函式在繼承層次結構中總是會自動地從基類傳播下去的。因此派生類中過載的虛函式的virtual可以省略。
8、虛函式用於繼承結構層次中的基類與子類。除了基類與子類的函式名必須相同外,連引數型別、個數和順序都要相同。
13、寫開禁操作可以去掉常量或者常物件的常量性:(p441)
char *p = const_cast(max("hello", "world"));
多型 虛函式
繼承模式分為單繼承和多繼承 在多繼承中會有相應的一些問題產生,比如資料冗餘,二義性等問題,那麼我們要如何解決這種問題。利用虛繼承便可以解決,在虛繼承的時候由虛基表可以去除資料冗餘和二義性。那麼函式可不可以寫成是虛函式呢?寫成虛函式有什麼作用?在派生類裡重寫基類的虛函式可以實現多型。include u...
虛函式多型
虛函式訪問知識點 王道程式設計師求職寶典 p163 1 與普通函式一樣,虛函式可通過物件名來呼叫,此時編譯器採用靜態聯編。通過物件名訪問虛函式時,呼叫哪個類的函式取決於定義物件名的型別。物件是基類就調基類,物件是子類就調相應的子類。2 使用指標訪問非虛函式時,編譯器會根據指標本身的型別決定呼叫哪個函...
多型,虛函式,純虛函式
多型 借助虛函式,基類指標既可以使用基類 父類 的成員函式,也可以使用派生類 子類 的成員函式,它有多種形態,或多種表現方式,這就是多型 簡單說就是同一條語句可以執行不同的操作,看起來有不同表現方式,這就是多型。多型存在的三個條件 注意 派生類 子類 中的虛函式必須覆蓋 不是過載 基類 父類 中的虛...