2014-12-01 75 views
-1

我正在使用VS 2013並嘗試查看vptr和vftable如何在對象級別上工作。所以,我有以下類:單個虛擬桌面如何跟蹤新的虛擬功能?

#include<iostream> 
using namespace std; 

class baseClass 
{ 
public: 
    void nonVirtualFunc() {} 
    virtual void virtualNonOverriddenFunc() {} 
    virtual void virtualOverriddenFunc() {} 
}; 

class derivedClass : public baseClass 
{ 
public: 
    virtual void virtualOverriddenFunc() {} 
    virtual void derivedClassOnlyVirtualFunc() { cout << "derivedClass" << endl; } 
}; 


int main(int argc, char** argv) { 

    derivedClass derivedClassObj2; 
    cout << "Size of derivedClassObj: " << sizeof(derivedClassObj2) << endl; 

    return 0; 
} 

這是我所看到的在調試時: enter image description here

理論上應該有兩個vptrs。一個用於baseClass的vftable,另一個用於derivedClass跟蹤新添加的derivedClassOnlyVirtualFunc()。

但是,正如你所見,只有一個vptr/vftable。但機制工作正常。

我以爲有第二個vptr,我不能在觀察窗口看到,所以我打印出對象的大小。它是4個字節,表示只有一個指針存在。

那麼這是如何與新增虛擬功能?根據this應該有兩個vptrs。

編輯:我檢查了vftable的內存內容,因爲Serge建議並且確實有三個條目。 enter image description here 由於某種原因,它沒有顯示在調試器中。

乾杯。

+0

不,因爲當您創建派生對象時,vtable中的條目將被派生的虛擬函數的地址替換(如果派生的虛函數派生出來的話)。這是在構造對象時完成的,它解釋了爲什麼你不應該在構造函數/析構函數中調用虛函數。 – Borgleader 2014-12-01 15:42:48

+0

爲什麼要在對象中有兩個?一個就足夠了,派生類vtable基於基類,爲更多虛擬添加額外條目並替換其他條目以指向新實現。 – Deduplicator 2014-12-01 15:44:05

+0

@Borgleader:在ctors和dtors中調用虛函數很好。 – Deduplicator 2014-12-01 15:44:41

回答

1

vtable的實現依賴於編譯器。對象的大小(4字節)表明vtable不在對象中複製,因爲4個字節只是一個指針。我的理解是:

  • 有一個且只有一個虛表(*)每類(而不是每個對象)
  • 每個對象都有一個指向它的虛函數表(它的實際類的一個)
  • _vfptr是祖先類的屬性,調試器顯示它的祖先類下,因此只顯示該類

但可以肯定的真正_vtable包含了其他虛擬方法條目定義的方法...尾部呃調試器顯示的條目!

(*)當您考慮_vfptr陣列的內部組織時,事情變得更加困難。實際上,它可以被看作包含所有祖先類的vtable的副本。這裏,derivedClass的2個第一項對應於baseClass的vtable。但是如果你打開一個內存窗口,並檢查什麼在_vfptr地址(在你的例子中爲0x00d9ba68),你應該看到空條目之前的第三項(至少這是我的MSVC Express 2008顯示)。這第三個條目對應於功能derivedClassOnlyVirtualFunc,但不像前面所述的那樣由調試器顯示。

+0

1.即使vtable的* existance *(如果有)也是一個實現細節。 2.看看'std :: iostream'。根據我的計數,它有3個vtable,因爲每個實例都有3個vtable指針。 (在一些常見的實現上)。3.既不是基本類型,也不是既沒有虛擬基礎也沒有成員的類具有虛表和虛表指針。 – Deduplicator 2014-12-01 20:10:27

+0

@Serge謝謝。我確實看過記憶內容,似乎沒有第三項。我用內存截圖更新了原始問題。 – madu 2014-12-02 00:07:51

+0

@Serge你是對的。有一個條目。我在代碼中犯了一個錯誤。這次真是萬分感謝。奇怪爲什麼它不顯示。 – madu 2014-12-02 02:49:51