2011-04-11 60 views
3

如果我創建了一個非常簡單的類是這樣的:如果有虛擬方法,是否會創建vtable?

class A 
{ 
    public : 
    virtual void foo() 
    { 
    } 
}; 

(無虛析構函數)時,編譯器將創建虛表? 或者是現代編譯器足夠聰明以識別這種情況(這可能是一個錯誤的複製和粘貼),而不是爲這些類添加虛擬表?

+0

一種常用的技術是用第一個虛擬非內聯成員發出vtable。在這種情況下,我不知道什麼是回退,哪裏存在虛擬非內聯成員,但這不是內聯函數或模板實例化中的靜態問題。 – AProgrammer 2011-04-11 13:49:44

+2

虛擬析構函數只是強制類是多態的一種方式,如果碰巧沒有其他虛函數的話。 (如果您打算通過指向A的指針刪除派生類,那麼也需要這樣做)。 – 2011-04-11 13:53:55

+2

@AProgrammer - 編譯器可能不得不生成大量的vtable副本,並讓鏈接器將其整理出來。 – 2011-04-11 13:57:38

回答

5

v表是一個實現細節。編譯器使用虛擬函數的v表爲這個類創建一個。那些不,不會。

+1

什麼是一些替代方案? – 2011-04-11 13:34:26

+0

@Jason:看到[這個問題](http://stackoverflow.com/questions/4352032/a-question-about-virtual-mechanism-in-c)和[this one](http://stackoverflow.com/問題/ 5417829/how-can-c-virtual-functions-be-implemented-except-vtable) – 2011-04-11 13:35:52

+0

你說得對,它是一個實現細節,但是有沒有現代編譯器不這樣做? – 2011-04-11 13:40:09

2

編譯器無法確定該類不是在另一個編譯單元中派生的,因此它必須確保該調用正確依賴於該實例的運行時類型。

如果它使用一個vtable來解析虛擬調用,那麼將創建一個vtable。如果使用另一個實現,那麼將使用該機制。


舊版本: V表將被創建,因爲編譯器不能肯定的是,類將不會在另一個編譯單元導出。

+0

編譯器將設置機器以使虛擬調用按標準的要求工作。這個機器可能不是一個虛擬表。 – 2011-04-11 13:32:57

1

答案是編譯器必須生成一個v表。要明白爲什麼要考慮:

class B : public A 
{ 
    void foo() { do something interesting } 
} 

而且別的地方:

void bar (A& obj) 
{ 
obj.foo() 
} 

人們可以把握通過B型的目的是bar()B::foo()將被調用。這是良好的編程習慣總是對所有多態類的虛析構函數,因爲是允許一個polymorfically刪除A.在我們的情況下obj的類型是B

void bar2 (A& obj) 
{ 
delete obj; 
} 

可能不會像預期的那樣,因爲析構函數B永遠不會被調用。

相關問題