2010-07-22 122 views
2

請考慮以下源代碼。我有兩節課CBar和CFoo。 CFoo繼承自CBar。此源代碼的輸出是面向對象的基本繼承

Bar 
Foo 
Bar 

我期待

Bar 
Foo 
Foo 

我有什麼錯? 我在想,因爲CFoo對象有一個覆蓋CBar講話功能的Speak函數。當我從CFoo對象的CBar函數調用Speak()函數時,CFoo Speak函數將被執行。但是這個假設似乎是錯誤的。

class CBar 
{ 
    public: 
     void Speak() { 
      printf(" Bar \n"); 
     } 

     void DoStuff() { 
      this->Speak(); 
     } 
}; 


class Cfoo : public CBar 
{ 
    public: 
     void Speak() { 
      printf(" Foo \n"); 
     } 

     void DoStuff() { 
      CBar::DoStuff(); 
     } 
}; 



int _tmain(int argc, _TCHAR* argv[]) 
{ 
    CBar b; 
    b.Speak(); 

    Cfoo f; 
    f.Speak(); 

    f.DoStuff(); 
    return 0; 
} 

回答

3

在C++中,你需要使用virtual啓用多態性。否則,所有Speak()正在做CFoo正在隱藏Speak()CBar

class CBar 
{ 
    public: 
     virtual void Speak() { // Note virtual keyword 
      printf(" Bar \n"); 
     } 

     void DoStuff() { 
      this->Speak(); 
     } 
}; 


class Cfoo : public CBar 
{ 
    public: 
     void Speak() { // Overrides the virtual method Speak() 
      printf(" Foo \n"); 
     } 

     void DoStuff() { // Hides CBar::DoStuff() method 
      CBar::DoStuff(); 
     } 
}; 



int _tmain(int argc, _TCHAR* argv[]) 
{ 
    CBar b; 
    b.Speak(); 

    // Speak() is a virtual function, so calling Speak() on a CFoo or 
    // a CBar pointer will call the most derived implementation of Speak(). 
    Cfoo f; 
    f.Speak(); 

    /* My example */ 
    // Since CFoo "is-a" CBar, this conversion is safe. 
    CBar* bar = &f; 
    // Since Speak() is a virtual function, this will call CFoo's implementation 
    // of Speak(), not CBar's. 
    bar->Speak(); 
    /* End example */ 

    // Because CBar::DoStuff() is hidden, this calls CFoo::DoStuff() instead. 
    f.DoStuff(); 
    return 0; 
} 
+0

謝謝,我知道這將是簡單的事情。 – 2010-07-22 18:03:30

3

Speak不是多態函數。

也就是說,因爲它沒有標記爲virtual任何對它的調用都是靜態確定的。因此在CBar,this->Speak();將始終指CBar::Speak

如果您將函數設爲虛函數,則將根據動態類型而非靜態類型選擇對該函數的調用,並調用您期望的函數。