建構函式:為對象分配儲存空間,使一個對象初始化;
解構函式:在該對象生命期完結時做相應的掃尾工作並釋放由建構函式分配的記憶體;
建構函式不能是虛函數的原因:
自己的話:【只有基類指標指向子類對象時,虛函數才用意義。當一個基類指標指向子類對象時,子類對象已經構造好了,已經沒有動態綁定的必要了,所以虛函數不能是虛函數。】
從概念上來說,如前所述,虛函數機制只有在應用於地址時才有效,因為地址在編譯階段提供的類型資訊不完全。建構函式的功能是為一個對象在記憶體中分配空間,也就是說,此時該對象的類型已經確定了,編譯系統確切的知道應該調用哪一個類的建構函式,不需要也不可能應用動態綁定。
從實現上來說,每個對象的VPTR是需要建構函式來初始化的(當然是由編譯系統自動加進去的代碼來實現),在建構函式沒有調用之前,VPTR沒有形成,根本就不可能實現動態綁定。
當建構函式內部有虛函數時,會出現什麼情況呢?結果是,只有在該類中的虛函數版本被調用,也就是說,在建構函式中,虛函數機制不起作用了,調用虛函數如同調用一般的成員函數一樣。
解構函式可以是虛函數:
解構函式可以是虛函數,而且應該被聲明為虛函數。與一般成員函數相似,解構函式被調用時,對象的構造已經完成,VPTR和VTABLE也已被正確初始化,因此虛解構函式在實現上是可能的。
從設計角度來看,解構函式的任務是釋放記憶體,因此它必須確切知道被釋放的對象的類型,否則可能破壞有用的資料,產生不可預知的後果。例如,我們用基類指標指向了衍生類別對象,那麼釋放記憶體時,必須是釋放衍生類別對象的儲存空間。所以,解構函式經常被聲明為虛函數。由於效率上的原因,並不把解構函式預設為虛函數。但作為一條實踐經驗,可以給有虛函數的每個基類聲明虛解構函式。
當解構函式內部有虛函數時,又如何工作呢?與建構函式相同,只有“局部”的版本被調用。但是,行為相同,原因是不一樣的。建構函式只能調用“局部”版本,是因為調用時還沒有衍生類別版本的資訊。解構函式則是因為衍生類別版本的資訊已經不可靠了。我們知道,解構函式的調用順序與建構函式相反,是從衍生類別的解構函式到基類的解構函式。當某個類的解構函式被調用時,其下一級的解構函式已經被調用了,相應的資料也已被丟失,如果再調用虛函數的最後一級的版本,就相當於對一些不可靠的資料進行操作,這是非常危險的。因此,在解構函式中,虛函數機制也是不起作用的。