物件導向 多型

2021-07-28 06:17:32 字數 2002 閱讀 1324

多型可以簡單的概括為「乙個介面,多種方法」,在程式執行過程中才決定呼叫的函式,簡單的說就是,允許將子類型別的指標賦值給父類型別的指標,賦值後,父類物件就可以根據當前賦給它的子類物件的特徵以不同的方式執行。

容易混淆的兩個概念:

是指允許存在多個同名的函式,而這些函式的參數列不同(或許引數個數不同,或許引數的型別不同,或許兩者都不同)。其實,過載的實現是編譯器根據函式不同的參數列,對同名函式的名稱做修飾,然後這些同名函式就成了不同的函式(編譯器是這麼認為的)。

對於過載的兩個函式的呼叫,在編譯器編譯期間就已經確定下來了,是靜態的。也就是說他們的位址在編譯期間就繫結了(早繫結),因此和多型無關,與物件導向無關。

又稱靜態多型,是指子類重新定義父類的虛函式的做法。當子類重新定義了父類的虛函式之後,父類的指標根據賦給它的不同的子類指標,動態的呼叫屬於該子類的函式,這樣的呼叫無法在編譯期間確定(呼叫子類的虛函式的位址無法給出)。這才是真正的多型,也是物件導向的核心。

作用:我們知道,封裝可以隱藏實現的細節,使得**模組化;繼承的作用是可以擴充套件已存在的**模組(類);它們的目的都是為了**的重用。而多型是為了實現另乙個目的——介面重用。

實現多型時,必須使用基類型別的指標變數或者引用,使該指標指向該基類的不同派生類的物件,並通過該指標指向虛函式,這樣就可以實現動態多型了。

下面舉個實現多型的例子:

class animal

當在main()函式中執行pan->breathe()時,呼叫的就是fish物件的breathe函式。

當類中宣告虛函式時,編譯器會在類中生成乙個虛函式表,虛函式表是乙個儲存類成員函式指標的資料結構,虛函式表是由編譯器自動生成與維護的,virtual成員函式會被編譯器放入虛函式表中,存在虛函式時,每個物件中都有乙個指向虛函式表的指標(vptr指標)。

如下圖所示:

編譯器為每個類的物件提供乙個虛表指標vptr,這個指標指向物件所屬類的虛函式表。在程式執行時,根據物件的型別去初始化vptr,從而讓vptr正確的指向所屬類的虛表,從而在呼叫虛函式時,就能夠找到正確的函式。

fish fh;

animal *pan=&fh;

pan->breathe();

由於父類的指標pan實際指向的物件型別是子類的物件,因此vptr指向的子類fish 類的vtable,當呼叫pan->breathe()時,根據虛表中的函式位址找到的就是fish類的breathe()函式。正是由於每個物件呼叫的虛函式都是通過虛表指標來索引的,也就決定了虛表指標的正確初始化是非常重要的。換句話說,在虛表指標沒有正確初始化之前,我們不能夠去呼叫虛函式。

那麼虛表指標在什麼時候,或者說在什麼地方初始化呢?

c++是在建構函式中進行虛表的建立和虛表指標的初始化。

建構函式的呼叫順序:在構造子類物件時,要先呼叫父類的建構函式,此時編譯器只「看到了」父類,並不知道後面是否後還有繼承者,它初始化父類物件的虛表指標vptr,該虛表指標指向父類的虛表。當執行子類的建構函式時,子類物件的虛表指標vptr被初始化, 此時 vptr指向自身的虛表。當fish類的fh物件構造完畢後,其內部的虛表指標也就被初始化為指向fish類的虛表。

注意: 通過虛函式表指標vptr呼叫重寫函式是在程式執行時進行的,因此需要通過定址操作才能確定真正應該呼叫的函式。而普通成員函式是在編譯時就確定了呼叫的函式。在效率上,虛函式的效率要低很多。出於效率考慮,沒有必要將所有成員函式都宣告為虛函式

物件在建立的時,由編譯器對vptr指標進行初始化,只有當物件的構造完全結束後vptr的指向才最終確定,到底是父類物件的vptr指向父類虛函式表還是子類物件的vptr指向子類虛函式表。

物件導向 多型

繼承是多型的基礎,是指物件的多種形態 1.引用的多型 1 父類的引用可以指向本類的物件 2 父類的引用可以指向子類的物件 注意 子類的引用不能指向父類的物件 2.方法的多型 1 建立本類物件時,呼叫的方法是本類的方法 2 建立子類物件時,呼叫的方法是子類重寫的方法或是繼承的方法 注意 如果是子類獨有...

物件導向 多型

多型 可以理解為事物存在的多種體現形態。人 男人,女人 動物 貓,狗。貓 x new 貓 動物 x new 貓 1,多型的體現 父類的引用指向了自己的子類物件。父類的引用也可以接收自己的子類物件。2,多型的前提 必須是類與類之間有關係。要麼繼承,要麼實現。通常還有乙個前提 存在覆蓋。3,多型的好處 ...

物件導向 多型

多型 引用變數具體會所指向哪個類的例項物件,以及發出的方法呼叫的是哪個類中的方法 必須執行時才能確定。父類引用 子類物件 自動向上轉型 呼叫方式時 只能呼叫父類的方法 子類重寫了,就是呼叫子類的。呼叫子類重寫的沒有,沒有就去呼叫繼承的父類方法。不能多繼承其實就是這個原因。a a new b this...