1. 程式人生 > >虛基類、虛擬函式、純虛擬函式的用法及其區別

虛基類、虛擬函式、純虛擬函式的用法及其區別

c程式的記憶體佈局是:
1. 程式碼段 code or text
2. 只讀資料段 ro data
3. 已初始化讀寫資料段 rw data
4. 未初始化讀寫資料段 bss
5. 堆 heap
6. 棧 stack
有時候也這麼說:
1. 棧
2. 堆
3. 全域性區或靜態區
4. 字元常量區
5. 程式程式碼區

首先,介紹下c語言的編譯執行過程,比方說一個main.c的檔案執行過程應當如下:
cpp(c前處理器)將mian.c處理為main.i
cc1(c編譯器)將main.i編譯為main.s
as(彙編器)將main.s彙編為main.o
ld(連結器)將main.o連結為可執行檔案

虛基類

當在多條繼承路徑上有一個公共的基類,在這些路徑中的某幾條匯合處,這個公共的基類就會產生多個例項(或多個副本),若只想儲存這個基類的一個例項,可以將這個公共基類說明虛基類。所以可以說,虛基類是為了只例項化一次基類存在的

虛擬函式:

虛擬函式的作用是實現動態聯編,也就是在程式的執行階段動態地選擇合適的成員函式,在定義了虛擬函式後,可以在基類的派生類中對虛擬函式重新定義,在派生類中重新定義的函式應與虛擬函式具有相同的形參個數和形參型別。以實現統一的介面,不同定義過程。如果在派生類中沒有對虛擬函式重新定義,則它繼承其基類的虛擬函式
1、 必須把動態聯編的行為定義為類的虛擬函式。  
2、類之間存在子型別關係,一般表現為一個類從另一個類公有派生而來。 
3、 必須先使用基類指標或者引用指向子型別的物件,然後直接或者間接使用基類指標呼叫虛擬函式。

純虛擬函式

是一種特殊的虛擬函式,它的一般格式如下:  

class <類名>
{
    virtual <型別><函式名>(<引數表>)=0;…
};

在許多情況下,在基類中不能對虛擬函式給出有意義的實現,而把它宣告為純虛擬函式,它的實現留給該基類的派生類去做。這就是純虛擬函式的作用。

總結

虛基類 
1, 一個類可以在一個類族中既被用作虛基類,也被用作非虛基類。 
2, 在派生類的物件中,同名的虛基類只產生一個虛基類子物件,而某個非虛基類產生各自的子物件。 
3, 虛基類子物件是由最派生類的建構函式通過呼叫虛基類的建構函式進行初始化的。 
4, 最派生類是指在繼承結構中建立物件時所指定的類。 
5, 派生類的建構函式的成員初始化列表中必須列出對虛基類建構函式的呼叫;如果未列出,則表示使用該虛基類的預設建構函式。 
6, 從虛基類直接或間接派生的派生類中的建構函式的成員初始化列表中都要列出對虛基類建構函式的呼叫。但只有用於建立物件的最派生 類的建構函式呼叫虛基類的建構函式,而該派生類的所有基類中列出的對虛基類的建構函式的呼叫在執行中被忽略,從而保證對虛基類子物件 只初始化一次。 
7, 在一個成員初始化列表中同時出現對虛基類和非虛基類建構函式的呼叫時,虛基類的建構函式先於非虛基類的建構函式執行。 

虛擬函式 
1, 虛擬函式是非靜態的、非內聯的成員函式,而不能是友元函式,但虛擬函式可以在另一個類中被宣告為友元函式。 
2, 虛擬函式宣告只能出現在類定義的函式原型宣告中,而不能在成員函式的函式體實現的時候宣告。 
3, 一個虛擬函式無論被公有繼承多少次,它仍然保持其虛擬函式的特性。 
4, 若類中一個成員函式被說明為虛擬函式,則該成員函式在派生類中可能有不同的實現。當使用該成員函式操作指標或引用所標識的物件時 ,對該成員函式呼叫可採用動態聯編。 
5, 定義了虛擬函式後,程式中宣告的指向基類的指標就可以指向其派生類。在執行過程中,該函式可以不斷改變它所指向的物件,呼叫不同 版本的成員函式,而且這些動作都是在執行時動態實現的。虛擬函式充分體現了面向物件程式設計的動態多型性。 純虛擬函式 版本的成員函式,而且這些動作都是在執行時動態實現的。虛擬函式充分體現了面向物件程式設計的動態多型性。

純虛擬函式 
1, 當在基類中不能為虛擬函式給出一個有意義的實現時,可以將其宣告為純虛擬函式,其實現留待派生類完成。 
2, 純虛擬函式的作用是為派生類提供一個一致的介面。 
3, 純虛擬函式不能實化化,但可以宣告指標。

為什麼基類的解構函式是虛擬函式?

  在實現多型時,當用基類操作派生類,在析構時防止只析構基類而不析構派生類的狀況發生。