複製鏈接
請複製以下鏈接發送給好友

vtable

鎖定
Vtable,計算機術語,中文譯名虛函數表,簡稱虛表。
每一個有虛函數的類都有這樣一個東西。實際上記錄了本類中所有虛函數的函數指針,也就是説是個函數指針數組的起始位置。
中文名
vtable
概    括
虛函數的概念
意    思
虛表
介    紹
記錄了所有虛函數的函數指針

目錄

vtable應用

Vtable虛表。比如virtual void TheSecondFun( )記錄在數組的第二個元素,當一個該類的對象實例調用TheSecondFun時就根據對應關係把第二個函數指針取出來,再去執行該函數,這種行為叫晚綁定,也就是説在運行時才知道調用的函數是什麼樣子的,而不是在編譯階段就確定的早綁定。

vtable處理

通常是由虛函數表(vtable)來實現的。
虛函數表的結構:它是一個函數指針表,每一個表項都指向一個函數。任何一個包含至少一個虛函數的類都會有這樣一張表。需要注意的是vtable只包含虛函數的指針,沒有函數體。實現上是一個函數指針的數組。虛函數表既有繼承性又有多態性。每個派生類的vtable繼承了它各個基類的vtable,如果基類vtable中包含某一項,則其派生類的vtable中也將包含同樣的一項,但是兩項的值可能不同。如果派生類覆寫(override)了該項對應的虛函數,則派生類vtable的該項指向覆寫後的虛函數,沒有覆寫的話,則沿用基類的值。
每一個類只有唯一的一個vtable,不是每個對象都有一個vtable,恰恰是每個同一個類的對象都有一個指針,這個指針指向該類的vtable(當然,前提是這個類包含虛函數)。那麼,每個對象只額外增加了一個指針的大小,一般説來是4字節。
在類對象的內存佈局中,首先是該類的vtable指針,然後才是對象數據。
在通過對象指針調用一個虛函數時,編譯器生成的代碼將先獲取對象類的vtable指針,然後調用vtable中對應的項。對於通過對象指針調用的情況,在編譯期間無法確定指針指向的是基類對象還是派生類對象,或者是哪個派生類的對象。但是在運行期間執行到調用語句時,這一點已經確定,編譯後的調用代碼能夠根據具體對象獲取正確的vtable,調用正確的虛函數,從而實現多態性。

vtable應用舉例

例:
實現多態:
class a
{
public:
virtual void fun1();
virtual void fun2();
private:
int i;
}
classb:public a
{
public:
virtual void fun2();
virtual void fun3();
private:
int j;
}
則class a 的內存layout為(win32 platform)
beginoflayoutofclassa
vtablepointer(pointertovtableofclassaseebelow)(4bytes)
inti(4bytes)
endoflayoutofclassa
vtableofclassa
beginofvtableofclassa
startaddressofa::fun1(4bytes)
startaddressofa::fun2(4bytes)
endofvtableofclassa
classb的內存layout為(win32platform)
beginoflayoutofclassb
vtablepointer(pointertovtableofclassbseebelow)(4bytes)
inti(4bytes)
intj(4bytes)
endoflayoutofclassb
vtableofclassb
beginofvtableofclassb
startaddressofa::fun1(4bytes)
startaddressofb::fun2(4bytes)
startaddressofb::func3(4bytes)
endofvtableofclassb
所以才有
a*p=newb;
p->fun2( ) 調 b::fun2( )