1. 構造函數為什么不能為虛函數?
a. 存儲空間角度: 虛函數的調用需要虛函數表指針,而該指針存放在對象的內容空間中,需要調用構造函數才可以創建他的值,否則即使開辟了空間,則虛表指針為隨機值,不會找到構造函數;若構造函數聲明為虛函數,那么由於對象還未創建,還沒有內存空間,更沒有虛函數表地址用來調用虛函數——構造函數了。
b. 使用上: 從實現上看,vbtl在構造函數調用后才建立,因而構造函數不可能成為虛函數;
虛函數主要是實現多態,在運行時才可以明確調用對象,根據傳入的對象類型,來調用函數當一個構造函數被調用時,它做的首要的事情之一是初始化它的V P T R。因此,它只能知道它是“當前”類的,而完全忽視這個對象后面是否還有繼承者。當編譯器為這個構造函數產生代碼時,它是為這個類的構造函數產生代碼- -既不是為基類,也不是為它的派生類(因為類不知道誰繼承它)。
c. 所以它使用的V P T R必須是對於這個類的V TA B L E。而且,只要它是最后的構造函數調用,那么在這個對象的生命期內, V P T R將保持被初始化為指向這個V TA B L E, 但如果接着還有一個更晚派生的構造函數被調用,這個構造函數又將設置V P T R指向它的 V TA B L E,等.直到最后的構造函數結束。V P T R的狀態是由被最后調用的構造函數確定的。這就是為什么構造函數調用是從基類到更加派生 類順序的另一個理由。
2.析構函數可以使用虛函數?
對象已經創建,虛表指針存放析構函數的地址,基類與派生類都含有析構虛函數,創建基類與子類對象,都含有各類的虛表指針,當寫通用函數時,運行根據傳入對象的類型確定析構函數的地址,然后調用該析構函數。 但析構卻不一定,我們往往通過基類的指針來銷毀對象。這時候如果析構函數不是虛函數,就不能正確識別對象類型從而不能正確調用析構函數。
