2013-04-26 101 views
0

所有:繼承類結構是什麼樣的?

當我在C++中研究基因多態性,我發現一個小例子在這裏:

#include <iostream> 
using namespace std; 
class Base{ 
public: 
virtual void f(float x){cout<<"Base::f(float)"<<x<<endl;} 
     void g(float x){cout<<"Base::g(float)"<<x<<endl;} 
     void h(float x){cout<<"Base::h(float)"<<x<<endl;} 
}; 

class Derived:public Base{ 
public: 
virtual void f(float x){cout<<"Derived::f(float)"<<x<<endl;} 
     void g(int x){cout<<"Derived::g(int)"<<x<<endl;} 
     void h(float x){cout<<"Derived::h(float)"<<x<<endl;} 
}; 
int main(void){ 
    Derived d; 
    Base *pb=&d; 
    Derived *pd=&d; 

    //Good:behavior depends solely on type of the object 
    pb->f(3.14f);  //Derived::f(float)3.14 
    pd->f(3.14f);  //Derived::f(float)3.14 

    //Bad:behavior depends on type of the pointer 
    pb->g(3.14f);  //Base::g(float)3.14 
    pd->g(3.14f);  //Derived::g(int)3(surprise!) 

    //Bad:behavior depends on type of the pointer 
    pb->h(3.14f);  //Base::h(float)3.14(surprise!) 
    pd->h(3.14f);  //Derived::h(float)3.14 


    return 0; 
} 

研究虛擬功能後,我覺得我有這個想法是如何的多晶型的工作,但仍存在一些在這段代碼中,我不想打擾某人解釋代碼是如何工作的,我只需要能夠向我展示Derived類中的詳細信息的人(不需要太多細節,只顯示方法函數指針(或索引)如何排列在Vtable和結構中對於那些沒有虛擬繼承的)。

從PB-> H(3.14f); //Base::h(float)3.14(surprise!) 我想應該有幾個vtables,對嗎?

謝謝!

+0

你是對的。這些函數應該是'virtual',它將爲每個類的類型提供一個vtable。 – 2013-04-26 19:08:06

+0

對不起德魯,這是我可憐的英語!這是工作代碼,我只想知道一些關於Derived Class結構的內部細節? – Kuan 2013-04-26 19:23:16

回答

2

你的代碼只中有一個多態(virtual)成員函數簽名:f(float)。其他三個功能,g(float)g(int),並且h(float)不虛。由於你的「(驚喜!)」的評論是呼籲g()h()後,我猜你要麼驚訝的是,這些功能是不是多態的,或者你實際上是由非多態函數的行爲感到驚訝。

如果你感到驚訝,g()h()並不多態,實現virtual每個多態函數之前。如果一個函數沒有聲明virtual,也只會是多態的,如果它具有相同的簽名在基類中的虛擬函數(這也意味着你在Derivedvirtual是多餘的,但我個人覺得,這些多餘的使用virtual是很好的風格)。由於virtual僅在f(float)之前出現,因此只有f(float)將是多態的。

由於h()不是多態,因此通過基址指針調用h()調用h()的基礎版本並不奇怪。

關於g(),派生類中的名稱隱藏了基類中的任何相應名稱,除非通過using聲明返回。這就是爲什麼pd->g(3.14f)調用Derived::g(int)即使Base::g(float)是更好的匹配。 Base::g不可見。如果您將using Base::g;放在派生類中,它將調用浮點版本g()。 (請注意,virtual也就沒有什麼區別了g()這裏,因爲g(int)g(float)是不同的函數簽名 - 有沒有辦法一個會覆蓋其他。)

HTH

+0

感謝Adam,我不知道你是否可以給我一些物理結構方面的解釋,比如指針如何找到相應函數的位置? – Kuan 2013-04-26 19:26:48

+0

@Kuan:多態函數的實現不是標準的一部分,所以我可以給出的任何實現細節可能是錯誤的,從編譯器到編譯器。然而,標識符(例如,一個指針)放置在多態類實例的開始處,用於標識派生類型或查找虛擬調用的代碼/數據偏移表。有時在每個實例中有多個這樣的標籤(通常具有多重繼承)。這些表格的細節因平臺而異。相反,學習所需的行爲更好。 – 2013-04-26 19:37:44

+0

感謝Adam,但是我想知道你是否可以給我一些最好的提示,以便如何記住或分類與虛擬繼承/非虛擬繼承,重載,覆蓋和隱藏相關的規則?或者你認爲哪些規則最重要? – Kuan 2013-04-26 20:22:40