程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> VC >> vc教程 >> VC++深入詳解:函數的覆蓋和隱藏

VC++深入詳解:函數的覆蓋和隱藏

編輯:vc教程

  1.函數的覆蓋

  在上一節介紹多態性的時候,我們給出了下面的代碼片段:

  例2-19

   class animal
  {
  public:
     …
   virtual void breathe()
   {
     cout<<"animal breathe"<<endl;
   }
  };
  class fish:public animal
  {
  public:
   void breathe()
   {
     cout<<"fish bubble"<<endl;
   }
  };

  在基類animal的breathe函數前添加了virtual關鍵字,聲明該函數為虛函數。在派生類fish中重寫了breathe函數,我們注意到,fish類的breathe函數和animal類的breathe函數完全一樣,無論函數名,還是參數列表都是一樣的,這稱為函數的覆蓋(override)。構成函數覆蓋的條件為:

  n 基類函數必須是虛函數(使用virtual關鍵字進行聲明)。

  n 發生覆蓋的兩個函數要分別位於派生類和基類中。

  n 函數名稱與參數列表必須完全相同。

  由於C++的多態性是通過虛函數來實現的,所以函數的覆蓋總是和多態關聯在一起。在函數覆蓋的情況下,編譯器會在運行時根據對象的實際類型來確定要調用的函數。

  2.函數的隱藏

  我們再看例2-20的代碼:

  例2-20

  class animal
  {
  public:
     …
   void breathe()
   {
     cout<<"animal breathe"<<endl;
   }
  };
  class fish:public animal
  {
  public:
void breathe()
   {
     cout<<"fish bubble"<<endl;
   }
  };

  你看出來這段代碼和例2-19所示代碼的區別了嗎?在這段代碼中,派生類fish中的breathe函數和基類animal中的breathe函數也是完全一樣的,不同的是breathe函數不是虛函數,這種情況稱為函數的隱藏。所謂隱藏,是指派生類中具有與基類同名的函數(不考慮參數列表是否相同),從而在派生類中隱藏了基類的同名函數。

  初學者很容易把函數的隱藏與函數的覆蓋、重載相混淆,我們看下面兩種函數隱藏的情況:

  (1)派生類的函數與基類的函數完全相同(函數名和參數列表都相同),只是基類的函數沒有使用virtual關鍵字。此時基類的函數將被隱藏,而不是覆蓋(請參照上文講述的函數覆蓋進行比較)。

  (2)派生類的函數與基類的函數同名,但參數列表不同,在這種情況下,不管基類的函數聲明是否有virtual關鍵字,基類的函數都將被隱藏。注意這種情況與函數重載的區別,重載發生在同一個類中。

  下面我們給出一個例子,以幫助讀者更好地理解函數的覆蓋和隱藏,代碼如例2-21所示。

  例2-21

  class Base
  {
  public:
    virtual void fn();
  };
  class Derived : public Base
  {
  public:
    void fn(int);
  };
  class Derived2 : public Derived
  {
  public:
    void fn();
  };

  在這個例子中,Derived類的fn(int)函數隱藏了Base類的fn()函數,Derived類fn(int)函數不是虛函數(注意和覆蓋相區別)。Derived2類的fn()函數隱藏了Derived類的fn(int)函數,由於Derived2類的fn()函數與Base類的fn()函數具有同樣的函數名和參數列表,因此Derived2類的fn()函數是一個虛函數,覆蓋了Base類的fn()函數。注意,在Derived2類中,Base類的fn()函數是不可見的,但這並影響fn函數的覆蓋。

  當隱藏發生時,如果在派生類的同名函數中想要調用基類的被隱藏函數,可以使用“基類名::函數名(參數)”的語法形式。例如,要在Derived類的fn(int)方法中調用Base類的fn()方法,可以使用Base::fn()語句。

  有的讀者可能會想,我怎樣才能更好地區分覆蓋和隱藏呢?實際上只要記住一點:函數的覆蓋是發生在派生類與基類之間,兩個函數必須完全相同,並且都是虛函數。那麼不屬於這種情況的,就是隱藏了。

  最後,我們再給出一個例子,留給讀者思考,代碼如例2-22所示(EX09.CPP)。

  例2-22

  #include <iOStream.h>
  class Base
  {
  public:
     virtual void xfn(int i)
     {
       cout<<"Base::xfn(int i)"<<endl;
     }
     void yfn(float f)
     {
       cout<<"Base::yfn(float f)"<<endl;
     }
     void zfn()
     {
       cout<<"Base::zfn()"<<endl;
     }
  };
  class Derived : public Base
  {
  public:
     void xfn(int i) //覆蓋了基類的xfn函數
     {
       cout<<"Drived::xfn(int i)"<<endl;
     }
     void yfn(int c) //隱藏了基類的yfn函數
     {
       cout<<"Drived::yfn(int c)"<<endl;
     }
     void zfn()   //隱藏了基類的zfn函數
     {
       cout<<"Drived::zfn()"<<endl;
     }
  };
  void main()
  {
     Derived d;
     Base *pB=&d;
     Derived *pD=&d;
     pB->xfn(5);
     pD->xfn(5);
     pB->yfn(3.14f);
     pD->yfn(3.14f);
     pB->zfn();
     pD->zfn();
  }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved