C++ Primer學習筆記(14)——虛函數的實現機制、純虛函數

來源:互聯網
上載者:User

標籤:虛函數   純虛函數   多態   c++   

在行文之前查閱了相關書籍,參考了一些別人的部落格,在這裡謝謝大家的分享!希望自己和大家在學習語言的道路上漸行漸遠,一直走下去~~~

上一篇文章中說道,C++ 的三個基本特質是 封裝、繼承、多態。

多態性是將介面與實現進行分離。用形象的語言解釋就是實現已共同的方法,但因個體差異而採用不同的策略。

多態包括靜多態和動多態,分別在編譯和運行過程中實現。而動多態是由虛函數來實現的,其實現機制體現了C++的神秘性。

1.虛函數的實現機制

虛函數是那些以 virtual 關鍵字修飾的成員函數,是用來實現多態的。

兩個重要的關鍵詞揭示了它的神秘面紗 : 虛表、虛指標。每個類用了一個虛表,每個類對象用了一個虛指標。

具體示範如下:

class A{public:    virtual void f();    virtual void g();private:    int a;};class B : public A{public:    void f();   // 覆蓋父類A中的虛函數f()private:    int b; };

因為 A 有 virtual void f( ) ,和 g( ),所以編譯器為 A 類準備了一個虛表 vtableA,內容如下:

B 繼承了A,所以裡面也有繼承於A的虛函數,故B也有一個虛表vtableB:

PS:因為B:: g是重寫了的,所以B的虛表的g放的是B::g的入口地址,而f 還是A:: g 的入口地址。

當執行B bt; 定義類對象的時候,編譯器分配空間時,除了 A 的int a 成員 , B的 int b 成員,還分配了指向B的虛表vtableB 的指標vptr , 對象bt 的布局如下:

其中,虛表指標總是在最前面的。

當執行下面的語句時:

A *pa = &bt;  //一個A 類型的指標,指向B類型的對象bt

pa ->g( ) 實際上是由 指標vptr指向B的虛表vtableB,然後去裡面尋找g()函數。可以看到,vtableB裡面是 B:: g( ),即B 自己的g( ),而不是A 的g( )。
這就是多態。

總結:

要知道 虛函數實現多態的機制,謹記虛表、虛指標。能夠列出父類和子類的虛表,以及子類對象的虛指標,就不難理解這個機制了。

2. 純虛函數(pure virtual function)

很多時候,定義一個類的對象是沒有意義的,例如,動物這個類,由它可以派生出大象、獅子、猴子等子類,但動物本身產生對象是沒有實際意義的。為瞭解決這個問題,提出了純虛函數的概念。
假如定義的虛函數為:

virtual void animals(string& name, int age){}

那麼如下就是純虛函數:

virtual void animals(string& name, int age) = 0;   // 函數體直接為0 的虛函數

存在純虛函數的類稱為 抽象類別,是一個單純地介面,抽象類別本身執行個體化,即不能產生對象,只能也必須在衍生類別中去執行個體化。

什麼情況下使用純虛函數呢?

  • 當想在基類中抽象出一種方法,且該基類只能被繼承,不能執行個體化

  • 這個方法必須在衍生類別中實現

針對上述兩點分別舉例說明:

1) 抽象類別不能執行個體化

例如:定義一個形狀的類(Cshape),但凡是形狀我們都要求能顯示自己,所以定義一個類如下:

class Cshape{    virtual show(){}};

我們不想將這個類執行個體化,首先會想到將show( )這個函數的函數體 { } 刪除,改為 virtual show( );

這時如果嘗試執行個體化 Cshape shape; 這樣其實是能夠通過編譯的,只能在串連的時候報錯。

那麼如何能夠在編譯的時候就報錯呢?

~~用純虛函數:

class Cshape{    virtual show() = 0; // 純虛函數不能執行個體化};

2) 該方法必須在衍生類別中實現

如上面的例子,show( ) 必須在每一個子類中實現,即在子類中重新定義自己的 show( ) 函數,若沒有定義,編譯時間就會報錯:

// 定義Cshape 的衍生類別,忘了定義show()class CPoint : public Cshape{  public:    void msg()    {        cout << " 這是一個點。" << endl;    }private:    float x;    float y;};// 下面執行個體化 CPoint 類的時候就會報錯!!!CPoint point1;

在編譯的時候就會報錯!!!

~~~~
這是不是一個預防在衍生類別中實現基類的方法? (^__^)

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

C++ Primer學習筆記(14)——虛函數的實現機制、純虛函數

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.