2009-09-05 83 views
10

更新:用直線方法調用示例替換了析構函數示例。C++繼承/ VTable問題

嗨,

如果我有以下代碼:

class a 
{ 
public: 
    virtual void func0(); // a has a VTable now 
    void func1(); 
}; 
class b : public a 
{ 
public: 
    void func0() { a::func0(); } 
    void func2(); 
}; 
  1. 是否有虛函數表B中? B沒有虛函數,但從b :: func0()調用:: func0()
  2. func1駐留在VTable中嗎?這不是虛擬的。
  3. func2是否駐留在VTable中?
  4. 如果b :: func0()中沒有a :: func0()調用,上面的答案會不同嗎?

感謝

+5

如果你在這樣的問題中告訴你正在使用什麼編譯器,我會很高興。虛擬表格是特定於實現的,儘管要努力將其格式標準化。 – 2009-09-05 16:08:53

+2

'b :: func0' **是**虛擬 – 2009-09-05 18:02:38

回答

19

如果你聲明虛擬函數,你也應該聲明你的析構函數是虛擬的;-)。

  1. B具有一個虛擬表,因爲它有一個虛擬的功能,即func0()。如果您在基類中聲明一個函數(包括析構函數)爲虛擬的,則其所有派生類都將具有相同簽名虛擬函數。這將導致他們有一個虛擬表。而且,即使您沒有明確聲明func0,B也會擁有該vtable。

  2. 非虛函數不通過vtables引用。

  3. 請參閱第2

  4. 號類虛函數表是基於類聲明構成。不考慮班級功能的身體(更不用說其他功能)。因此,B有一個vtable,因爲它的功能func0()是虛擬的。

還有一個棘手的細節,雖然它不是你的問題的要點。你聲明你的函數B::func0()爲內聯。在gcc編譯器中,如果虛函數聲明爲內聯,它將保留其在虛表中的插槽,該插槽指向爲該內聯函數發出的特殊函數(計算爲獲取其地址,這會使內聯發射)。這意味着,函數是否內聯不會影響vtable中槽的數量以及它對類的必要性。

+0

已更新。另外,基本上,如果函數在繼承層次結構中的任何*基類中聲明爲虛擬,那麼即使直接基類(1級以上)不會將其標記爲虛擬,該函數也是虛擬的? – jameszhao00 2009-09-05 16:49:08

+0

顯着的答案。應該是被接受的。從我+1。 – 2009-09-05 18:17:18

+0

@ jameszhao00:也更新了答案。你知道它是正確的:如果任何間接基類(即當前類的某個父類的某個父類的父類)聲明瞭虛函數,那麼它在當前類中也是虛擬的。請注意,重載函數(void f(int)與void f(double)相比)被視爲不同的函數。 – 2009-09-10 12:49:59

5
  1. 是的,因爲它的基類有一個;它的析構函數也是虛擬的(即使你沒有聲明它是虛擬的),因爲基類的析構函數是虛擬的。

  2. 沒有

  3. 號其實我並不認爲當前的代碼是合法的:編譯器將調用析構函數,如果你不」它調用在B的析構函數即使t明確地從〜B調用〜A;所以我認爲即使編譯器允許你也不應該從〜B調用〜A。

+0

對不起。我不應該使用析構函數作爲例子。更新。 – jameszhao00 2009-09-05 16:41:54

3

參照更新的例子:

  1. 是,b具有虛表。注意b :: func0()是虛擬的(重寫a :: func0()),即使你沒有明確地將它標記爲虛擬的。奇怪的C++「漏洞」,我猜。
  2. 編號非虛函數不駐留在vtable中。
  3. 請參閱2.
  4. 否。您已覆蓋a:func0();無論你是否調用:: func0()都沒關係。

一些額外的注意事項(編譯器相關的,但這些都是很常見的概括):

  • b每個實例都將有一個指向虛函數表,因爲你從一個類派生具有虛擬功能。
  • 即使您沒有定義b :: func0(),情況也會如此
  • 在這種情況下,編譯器可能有b點的情況下,以一個的靜態虛表,或者它可能爲b創建一個靜態虛函數表,並用指針填充它指向的一個成員。
  • 但它仍然需要,這樣就可以適當地通過指針一個訪問b一個實例。
1
  • 如果基類的功能是虛擬的,然後如果你重寫派生類的功能它是含蓄虛擬,即使你沒有明確指定。如果類具有虛函數,那麼它有一個v表。
  • 存在的虛函數表只有虛函數,功能1不會駐留在虛函數表
  • 函數2不會駐留在虛函數表一樣的道理以上
  • 創建虛表的不依賴於你是否調用從基類,函數或從別的地方。函數調用不決定創建vtable。