c++多態:虛函數(爲什麼使用虛函數、那些函數能成爲虛函數)(一)

1、什麼是虛函數?來看看虛函數的官方定義:

在某基類中聲明爲 virtual 並在一個或多個派生類中被重新定義的成員函數,簡單來說,就是被virtual關鍵字修飾的成員函數。

作用:實現多態性(動多態),動多態又稱動態綁定或晚綁定。

 2.那爲什麼要使用虛函數呢?

結論:實現因對象的不同而調用其相應的函數

可以讓成員函數操作一般化,用基類的指針指向不同的派生類的對象時, 基類指針調用其虛成員函數,則會調用其真正指向對象的成員函數, 而不是基類中定義的成員函數(只要派生類改寫了該成員函數)。若不是虛函數,則不管基類指針指向的哪個派生類對象,調用時都 會調用基類中定義的那個函數。

文字理解起來不太形象,來代碼演示一下;


#include<iostream>
using namespace std;
class Father
{
    public:
        void print()
        {
            cout<<"This is Father"<<endl;
        }
};
 
class Son : public Father
{
    public:
        void print()
        {
            cout<<"This is Son"<<endl;
        }
};
 
int main()
{
    Father a;
    Son b;
    Father *p1 = &a;
   Father *p2 = &b;
    p1->print();
    p2->print();
    return 0;
}

運行結果爲:父類Show函數、父類show函數

用父類指針指向子類對象,如果不將Show函數聲明爲虛函數,最終調用的是父類Show函數,而不是我們派生後重寫的Show函數。如果將Show函數聲明爲虛函數,

class Father
{
    public:
        virtual void print(){cout<<"This is Father"<<endl;}
};
class Son : public Father
{
    public:
    void print(){cout<<"This is Father"<<endl;}
};

int main()
{

    Father a;
    Son b;
    Father *p1 = &a;
    Father *p2 = &b;
    p1->print();
    p2->print();
    return 0;
}

毫無疑問,class Father的成員函數print()已經成了虛函數,那麼class Son的print()成了虛函數了嗎?回答是Yes,我們只需在把基類的成員函數設爲virtual,其派生類的相應的函數也會自動變爲虛函數。所以,class Son的print()也成了虛函數。那麼對於在派生類的相應函數前是否需要用virtual關鍵字修飾,那就是你自己的問題了(語法上可加可不加,不加的話編譯器會自動加上,但爲了閱讀方便和規範性,建議加上)。

現在重新運行main的代碼,這樣輸出的結果就是This is Father和This is Son了。

3.虛函數的應用

進一步思考,爲什麼要用父類指針指向子類對象呢?這根本不需要聲明爲虛函數啊,直接定義一個子類對象,或是用子類指針指向子類對象,再來調用print函數,即使不用聲明爲虛函數,也能調用我們派生後重寫的print函數。

雖然這樣說,但是實際開發過程中不是這樣的,當我們使用一些類庫、框架的時候,這些類庫、框架是事先就寫好的。我們在使用的時候不能直接修改類庫的源碼,我們只能派生類庫中的類來覆蓋一些成員函數以實現我們的功能,但這些成員函數有的是由框架調用的。這種情況下,用虛函數是很好的辦法。

4.那些函數可以成爲虛函數?

成爲虛函數的條件:1.能取地址  2.依賴對象調用

  1. 析構函數:可以(派生類裏的析構函數最好是虛函數,否則派生類中如有空間的開闢會造成派生類內存泄漏)
  2. 普通的類成員方法:可以

以下函數不能成爲虛函數:

  1. 構造函數:不能,(此時對象還沒有產生)
  2. static成員方法:不能。(不依賴對象調用)
  3. inline函數:不能。(inline函數在編譯時被展開,用函數體去替換函數,而虛函數是在運行期間才動態綁定。)
  4. 普通的方法:不能,(友元函數不屬於類的成員函數,只能重載,不能覆蓋,函數覆蓋發生在繼承關係中)
  5. 友元:不能(友元函數不屬於類的成員函數,不能被繼承)

這篇是關於虛函數的由來,下一篇更虛函數的實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章