構造函數爲什麼不能是虛函數

從存儲空間角度看

虛函數對應一個指向vtable虛函數表的指針,這大家都知道,可是這個指向vtable的指針其實是存儲在對象的內存空間的。問題出來了,如果構造函數是虛的,就需要通過 vtable來調用,可是對象還沒有實例化,也就是內存空間還沒有,怎麼找vtable呢?所以構造函數不能是虛函數。

從使用角度

虛函數主要用於在信息不全的情況下,能使重載的函數得到對應的調用。構造函數本身就是要初始化實例,那使用虛函數也沒有實際意義呀。所以構造函數沒有必要是虛函數。虛函數的作用在於通過父類的指針或者引用來調用它的時候能夠變成調用子類的那個成員函數。而構造函數是在創建對象時自動調用的,不可能通過父類的指針或者引用去調用(沒有存在的必要),因此也就規定構造函數不能是虛函數。

構造函數不需要是虛函數,也不允許是虛函數

因爲創建一個對象時我們總是要明確指定對象的類型,儘管我們可能通過基類的指針或引用去訪問它但析構卻不一定,我們往往通過基類的指針來銷燬對象。這時候如果析構函數不是虛函數,就不能正確識別對象類型從而不能正確調用析構函數。

從實現上看

vbtl在構造函數調用後才建立,因而構造函數不可能成爲虛函數。從實際含義上看,在調用構造函數時還不能確定對象的真實類型(因爲子類會調父類的構造函數);而且構造函數的作用是提供初始化,在對象生命期只執行一次,不是對象的動態行爲,也沒有必要成爲虛函數

虛函數表實現角度

當一個構造函數被調用時,它做的首要的事情之一是初始化它的VPTR。因此,它只能知道它是“當前”類的,而完全忽視這個對象後面是否還有繼承者。當編譯器爲這個構造函數產生代碼時,它是爲這個類的構造函數產生代碼——既不是爲基類,也不是爲它的派生類(因爲類不知道誰繼承它)。所以它使用的VPTR必須是對於這個類的VTABLE。而且,只要它是最後的構造函數調用,那麼在這個對象的生命期內,VPTR將保持被初始化爲指向這個VTABLE, 但如果接着還有一個更晚派生的構造函數被調用,這個構造函數又將設置VPTR指向它的VTABLE,等直到最後的構造函數結束。VPTR狀態是由被最後調用的構造函數確定的。這就是爲什麼構造函數調用是從基類到更加派生類順序的另一個理由。但是,當這一系列構造函數調用正發生時,每個構造函數都已經設置VPTR指向它自己的VTABLE。如果函數調用使用虛機制,它將只產生通過它自己的VTABLE的調用,而不是最後的VTABLE(所有構造函數被調用後纔會有最後的VTABLE)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章