關於類的建構函式不能為虛擬函式的幾點理由!

菜鳥加貝的爬升發表於2013-10-17
  • 從儲存空間角度

虛擬函式對應一個vtable,這大家都知道,可是這個vtable其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,所以無法找到vtable。所以建構函式不能是虛擬函式。

  • 從使用角度

虛擬函式主要用於在資訊不全的情況下,能使過載的函式得到其對應的呼叫。建構函式本身就是要初始化例項,那使用虛擬函式也沒有實際意義呀。所以建構函式沒有必要是虛擬函式。虛擬函式的作用在於通過父類的指標或者引用來呼叫它的時候能夠變成呼叫子類的那個成員函式。而建構函式是在建立物件時自動呼叫的,不可能通過父類的指標或者引用去呼叫,因此也就規定建構函式不能是虛擬函式。

  • 建構函式不需要是虛擬函式,也不允許是虛擬函式

因為建立一個物件時我們總是要明確指定物件的型別,儘管我們可能通過基類的指標或引用去訪問它但析構卻不一定,我們往往通過基類的指標來銷燬物件。這時候如果解構函式不是虛擬函式,就不能正確識別物件型別從而不能正確呼叫解構函式。

  • 從實現角度

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

  • 從編譯器的角度

當一個建構函式被呼叫時,它做的首要的事情之一是初始化它的VPTR。因此,它只能知道它是"當前"類的,而完全忽視這個物件後面是否還有繼承者。 當編譯器為這個建構函式產生程式碼時,它是為這個類的建構函式產生程式碼- -既不是為基類,也不是為它的派生類(因為類不知道誰繼承它)。所以它使用的VPTR必須是對於這個類的VTABLE。而且,只要它是最後的建構函式呼叫,那麼在這個物件的生命期內, VPTR將 保持被初始化為指向這個VTABLE, 但如果接著還有一個更晚派生的建構函式被呼叫,這個建構函式又將設定V P T R指向它的 V TA B L E,等.直到最後的建構函式結束。V P T R的狀態是由被最後呼叫的建構函式確定的。這就是為什麼建構函式呼叫是從基類到更加派生 類順序的另一個理由。但是,當這一系列建構函式呼叫正發生時,每個建構函式都已經設定V P T R指向它自己的VTABLE。如果函式呼叫使用虛機制,它將只產生通過它自己的VTABLE的呼叫,而不是最後的V TA B L E(所有建構函式被呼叫後才會有最後的VTABLE)。

相關文章