天天看點

虛函數表又是怎樣實作的?

每個含有虛函數的類有一張虛函數表(vtbl),表中每一項指向一個虛函數的位址,實作上是一個函數指針的數組。
虛函數表既有繼承性又有多态性。每個派生類的vtbl繼承了它各個基類的vtbl,如果基類vtbl中包含某一項,則其派生類的vtbl中也将包含同樣的一項,但是兩項的值可能不同。如果派生類覆寫(override)了該項對應的虛函數,則派生類vtbl的該項指向重載後的虛函數,沒有重載的話,則沿用基類的值。
在類對象的記憶體布局中,首先是該類的vtbl指針,然後才是對象資料。在通過對象指針調用一個虛函數時,編譯器生成的代碼将先擷取對象類的vtbl指針,然後調用vtbl中對應的項。對于通過對象指針調用的情況,在編譯期間無法确定指針指向的是基類對象還是派生類對象,或者是哪個派生類的對象。但是在運作期間執行到調用語句時,這一點已經确定,編譯後的調用代碼能夠根據具體對象擷取正确的vtbl,調用正确的虛函數,進而實作多态性。
分析一下這裡的思想所在,問題的實質是這樣,對于發出虛函數調用的這個對象指針,在編譯期間缺乏更多的資訊,而在運作期間具備足夠的資訊,但那時已不再進行綁定了,怎麼在二者之間作一個過渡呢?把綁定所需的資訊用一種通用的資料結構記錄下來,該資料結構可以同對象指針相聯系,在編譯時隻需要使用這個資料結構進行抽象的綁定,而在運作期間将會得到真正的綁定。這個資料結構就是vtbl。可以看到,實作使用者所需的抽象和多态需要進行後綁定,而編譯器又是通過抽象和多态而實作後綁定的.