農林漁牧網

您現在的位置是:首頁 > 林業

面嚮物件語言的核心!動態多型簡單講解

2022-11-29由 王萌曼漫 發表于 林業

基類指標可以呼叫派生類的函式嗎

面嚮物件語言的核心!動態多型簡單講解

動態多型性

1)為什麼需要虛擬函式

為了說明虛擬函式的作用,我們先看一個程式例項。

【例1】沒有使用虛擬函式時的函式呼叫。

面嚮物件語言的核心!動態多型簡單講解

面嚮物件語言的核心!動態多型簡單講解

該程式的執行結果,我們已經標註在程式中。從前面的知識我們也可以很容易分析出它的執行結果。因為指標的型別決定了呼叫哪一個成員函式,所以,一個vehicle型別的指標呼叫vehicle的message()成員函式,即使它指向派生類car的物件。同樣,一個car型別的指標也呼叫car的message()成員函式。我們把這稱為早期聯編或靜態聯編,因為指標要呼叫哪一個函式是在編譯時就確定的。

那麼,當vehicle型別指標指向派生類car物件時,我們能不能透過該指標來呼叫派生類car的成員函式呢?在C++中,我們是可以做到的,這要用到C++的多型特性。

多型也稱為動態聯編或遲後聯編,因為到底呼叫哪一個函式,在編譯時不能確定,而要推遲到執行時確定。也就是說,要等到程式執行時,確定了指標所指向的物件的型別時,才能夠確定。

在C++中,動態聯編是透過虛擬函式來實現的。

我們知道,函式呼叫是透過相應的函式名來實現的。對於源程式進行編譯後,存放在記憶體中的可執行程式,函式實際上是一段機器程式碼,它是透過首地址進行標誌和呼叫的。例如,假定定義一個函式:

面嚮物件語言的核心!動態多型簡單講解

我們可以用下面的語句呼叫這個函式:

func();∥呼叫func函式

這是在源程式中呼叫函式的方法,它是用函式名操作的。

下面我們看看在可執行程式中函式呼叫是怎麼操作的,我們用匯編語言來說明,因為組合語言和機器語言(計算機可以直接執行的語言)是一一對應的。在可執行程式中,函式呼叫使用下面的方法:call[xxxxx]

其中,xxxxx代表存放函式程式碼記憶體空間的首地址。

面嚮物件語言的核心!動態多型簡單講解

2021超實用性的Python零基礎入門到進階影片原始碼

¥

2

淘寶

購買

call是彙編語句中的一條指令,意思是呼叫一個函式。實際操作過程是:儲存當前地址、保護現場,跳轉到xxxxx地址執行。正是基於這個原因,在C/C++中的函式名實際上是一個指標,該指標指向該函式段程式碼在記憶體中的首地址。

如何將源程式中的函式呼叫和函式體(也就是該函式在記憶體中的機器程式碼)聯絡起來呢?這件工作是由編譯器和連線程式來完成的。

在C/C++語言中,函式呼叫在程式執行之前就已經和函式體(函式的首地址)聯絡起來了。編譯器把函式體翻譯成機器程式碼,並記錄了函式的首地址。在對函式呼叫的源程式段進行編譯的時候,編譯器知道這個函式名的首地址在哪裡(它可以從生成的標誌符表中查到這個函式名對應的首地址),然後將這個首地址替換成函式名,一併翻譯成機器碼。這種編譯方法稱為早期或靜態聯編。

那麼,當vehicle型別的指標指向派生類物件時,我們能不能透過該指標來呼叫派生類的成員函式呢?從這種編譯方法來看,是不可能的。因為編譯器只會根據vehicle指標的型別尋找所要的成員函式。

如何實現下面這個功能呢?就是“當用基類指標呼叫成員函式時,是呼叫基類的成員函式,還是呼叫派生類的成員函式,不由指標的型別決定,而由指標指向的物件的型別決定”。換句話說,如果基類指標指向基類物件,就呼叫基類的成員函式;如果基類指標指向派生類物件,就呼叫派生類的成員函式。這時就要用到另外一種方法,稱為動態聯編或遲後聯編。到底呼叫哪一個函式,在編譯時不能確定,而要推遲到執行時確定。在C++中,動態聯編是透過虛擬函式來實現的。下面我們先介紹虛擬函式,然後討論動態聯編實現的原理。

好了,本文到此結束。如果對程式設計、計算機、程式設計師方面感興趣的話,歡迎私信聯絡我,隨時交流!點個關注,是對我莫大的鼓勵!