C++ 虛函數

來源:互聯網
上載者:User

一、虛方法
    C++不將允許CDog對象繼承了基類的屬性(資料)和功能(方法),然而C++還擴充了其多態性。也就是,允許將衍生類別對象賦值給指向基類的指標。
    CAnimal *panimal=new CDlog;
    然後可以通過這個指標來調用CAnimal類的任何方法。虛函數就可以做到這點。

   #include <iostream><br />#include <string><br />using namespace std;<br />class CAnimal<br />{<br /> public:<br /> CAnimal(){cout<< "animal constructor" <<endl;}<br /> virtual ~CAnimal(){cout<< "animal destructor" <<endl;}<br /> virtual void speek() const{cout<< "animal speek" <<endl;}<br /> void move () const {cout<< "animal move one tesp" <<endl;}<br />};<br />class CDog:public CAnimal<br />{<br /> public:<br /> CDog(){ cout<< "dog constructor" <<endl;}<br /> virtual ~CDog(){cout<< "dog destructor" <<endl;}<br /> virtual void speek() const {cout<< "dog speek" <<endl;}<br /> void move () const {cout<< "dog move one tesp" <<endl;}<br />};<br />int main()<br />{<br /> CAnimal *pDog = new CDog;<br /> pDog->speek();<br /> pDog->move();<br /> delete pDog;<br /> return 0;<br />}

    [root@local~ work]# ./a.out
    animal constructor
    dog constructor
    dog speek
    animal move one tesp
    dog destructor
    animal destructor

二、虛函數工作原理
    建立派生對象時,首先調用基類的建構函式,然後調用衍生類別的建構函式。說明了CDog對象被建立後的情景,注意CAnimal部分和CDog部分在記憶體中是相鄰的。

在類建立虛方法後,這個類必須被跟蹤虛方法。很多編譯器建立了虛函數表。每個類都有一個虛函數表,每個類對象都有一個執行虛函數表的指標(vptr或v-pointer)。每個對象的vptr都指向v-talbe;而對於每個虛方法,v-table都包含一個指向它的指標。建立CDog的CAnimal部分時,vptr被初始化指向v-table的正確部分。如

當CDog的建構函式被調用時,添加對象的CDog部分,並調整vptr指標使其指向CDog類中覆蓋的虛方法。如

 

 

 

使用CAnimal指標時,vptr將根據CAnimal指標指向的對象的實際類型指向正確的函數,這樣調用函數speak時,將調用正確的函數。
三、通過基類指標訪問衍生類別的方法
    如果只有衍生類別有該方法,基類沒有對應的虛方法,則不能通過CAnimal指標來訪問該方法。不過可以將CAnimal指標強制轉為CDog指標,但是CAnimal不是一個CDog,這樣做將是不安全的。
四、切除
    僅當通過指標或引用進行調用時,才能發揮虛函數的魔力,按值傳遞對象將不能發揮虛方法的魔力。
五、建立虛解構函式
     當指向衍生類別對象的指標被刪除時將發生什麼情況呢?如果解構函式時虛函數,將執行正確的操作:調用衍生類別的解構函式,衍生類別的解構函式會自動調用基類的解構函式,因此整個對象將被正確地銷毀。   
     經驗規則,如果類中任何一個函數都是虛函數,解構函式也應該是虛函數。
六、虛複製建構函式
    建構函式不能是虛函數,因此從技術上,不存在虛複製建構函式。然而有時候程式非常需要通過傳遞一個指向基類對象的指標,建立一個衍生類別對象的副本。一個常見的解決方案是,在基類建立一個clone方法,並將其設定為虛方法。clone方法建立當前類對象一個副本,並返回該副本。
    由於每個衍生類別都覆蓋了clone方法,因此他將建立衍生類別對象的一個副本。

#include <iostream><br />#include <string><br />using namespace std;<br />class CAnimal<br />{<br /> public:<br /> CAnimal(){cout<< "animal constructor" <<endl;}<br /> CAnimal(const CAnimal & ranimal){cout<< "animal copy constructor" <<endl;}<br /> virtual ~CAnimal(){cout<< "animal destructor" <<endl;}<br /> virtual void speek() const{cout<< "animal speek" <<endl;}<br /> virtual CAnimal* clone () {return new CAnimal(*this);}<br />};<br />class CDog:public CAnimal<br />{<br /> public:<br /> CDog(){ cout<< "dog constructor" <<endl;}<br /> CDog(const CDog & rdog){cout<< "dog copy constructor" <<endl;}<br /> virtual ~CDog(){cout<< "dog destructor" <<endl;}<br /> virtual void speek() const {cout<< "dog speek" <<endl;}<br /> void move() const {cout<< "dog move one step" <<endl;}<br /> virtual CAnimal* clone () {return new CDog(*this);}<br />};<br />int main()<br />{<br /> CAnimal *pDog = new CDog;<br /> pDog->speek();<br /> CAnimal *p = pDog->clone();<br /> p->speek();<br /> delete pDog;<br /> delete p;<br /> return 0;<br />}

 

    [root@local~ work]# ./a.out          
    animal constructor
    dog constructor
    dog speek
    animal constructor
    dog copy constructor
    dog speek
    dog destructor
    animal destructor
    dog destructor
    animal destructor

七、使用虛方法的代價
     由於包含虛方法的類必須維護一個v-table,因此使用虛方法會帶來一些開銷。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.