2014-01-06 77 views
0

當我有這樣的事情,當我有a* mya=new c();,我稱之爲a->displayStuff它調用Class a方法,當virtualClass a而不是Class b,它調用Class b方法。虛函數

由於Class c沒有實現此方法,因此此處應用了什麼規則?

class a 
{ 
public: 
void displayStuff() {} 
//other methods 
}; 

class b:public a 
{ 
public: 
virtual void displayStuff() {} 
//other methods 
}; 

class c:public b 
{ 
//other methods 
}; 
+1

你爲什麼要這樣做?這隻會讓任何想要使用類層次結構的人感到困惑。請記住,你應該編寫代碼,假設一個斧頭的瘋子最終會支持它。 – Sean

+0

我有一個考試,噢相信我,我們的教授會問我們這樣的問題:) – user2949483

回答

2

在第一個例子中,類A沒有虛函數。所以它的非虛函數displayStuff將被調用。在第二種情況下,當您將函數說明符virtual添加到類A中的函數時,相應的函數inclass B將重新定義此函數。所以在第二種情況下,類B的功能被調用,因爲虛擬函數指針表包含指向B類中定義的函數的指針。

+0

你是說在第一種情況下,我的對象是要搜索第一個非虛函數?而第二種情況下,我的對象會仰望「最近」的基類來使用它的方法? – user2949483

+1

在這兩種情況下,編譯器都會在類a中搜索名稱爲displayStuff的函數。在第一種情況下,它不是虛擬的,因此它在類a中找到,因此被調用。在第二種情況下,當您添加虛函數說明符時,編譯器也會找到該函數。但是,因爲它是虛擬的,所以編譯器訪問其中寫入了類b函數的地址的虛擬函數的指針表。所以它調用了類b的功能。 –

+1

假設每個具有虛擬函數的對象都包含一個指向虛擬函數指針表的指針會更簡單。由於類c沒有覆蓋類b的虛函數,所以表的內容與類b的相同。 –

1

由於類c沒有實現此方法,因此規則是什麼 適用於此?

繼承的規則適用。根據繼承的成員和繼承類型的可見性,類B中可見的成員將在類C中可見。在這種情況下,由於您公開繼承,所有公共成員都將公開顯示。因此,在B級公共虛成員函數將作爲C類公共虛函數可見

沒錯,但是當使用什麼和爲什麼當我有多個層次 繼承?

它的設計決定。請記住,非虛擬成員函數在編譯時綁定,因此,只有在打算調用函數之前,通過基指針進行的任何函數調用才能解析。 考慮場景

         Base 
             public: foo 
            / \ 
            / \ 
            /  \ 
            /  \ 
           /   \ 
           Derived1  Derived2  
           public: foo public: foo 

Base *p; 
std::cin>>cond; 
if (cond) 
    p = new Derived1(); 
else 
    p = new Derived1(); 
p->foo(); 

在上面的代碼,決定調用foo()(Derived1 :: foo的或Derived2的:: foo的),依賴於不能在運行時確定一些外部條件。實現這一點的唯一方法是創建一個vTable,只有在虛擬類中至少創建一個函數時,才能強制創建vTable(注意,基類中的任何虛函數在派生類中都保持虛擬)。

+0

確切的,但是何時使用什麼以及爲什麼當我有多級繼承? – user2949483

+0

這有幫助。非常感謝! – user2949483