首頁 > 軟體

C++淺析虛擬函式使用方法

2022-08-24 18:01:50

闡述虛擬函式作用和原理、純虛擬函式和虛擬函式的區別。

一、虛擬函式

首先來看下面這一段程式碼,首先建立兩個類,一個是Dog,另一個是Cat,他們有一個共同的屬性:Run。在定義中每個動物都需要建立一個類,比較繁瑣,所以在下面的例子中,我們可以把他們簡化。

#include <iostream>
using namespace std;
class Dog{
public:
    void Run(){
        cout<<"Dog->Run"<<endl;
    }    
};
class Cat{
public:
    void Run(){
        cout<<"Cat->Run"<<endl;
    }
};
int main()
{
    Dog d;
    d.Run();
    Cat c;
    c.Run();
    return 0;
}

這裡使用多型和虛擬函式,而Animal提供統一的介面,供子類使用,雖然程式碼繁瑣,但提高了整個工程的可延伸性和靈活性。

在普通函數前加上關鍵字 virtual 構成虛擬函式,子類需要重寫父類別的虛擬函式,這樣在呼叫的時候,會覆蓋掉父類別的虛擬函式 Run,去執行子類的Run。

#include <iostream>
using namespace std;
class Animal{
public:
    virtual void Run(){
        cout<<"Animal->Run"<<endl;
    }
};
class Dog :public Animal{
public:
    void Run(){
        cout<<"Dog->Run"<<endl;
    }    
};
class Cat:public Animal{
public:
    void Run(){
        cout<<"Cat->Run"<<endl;
    }
};
int main()
{
    Animal *ani;
    ani = new Dog;
    ani->Run();
    delete ani;
    ani = new Cat;
    ani->Run();
    delete ani;
    return 0;
}

結果如下:

所以在這裡只需要修改ani的指向就可以實現不同方法。如果不存在虛擬函式,把Animal類的關鍵詞virtual去掉會怎麼樣呢,顯然,他們會預設實現父類別Run的方法。

class Animal{
public:
    void Run(){
        cout<<"Animal->Run"<<endl;
    }
};

所以引入虛擬函式是為了實現動態多型,指向不同的子類來實現不同的方法。

二、虛擬函式與純虛擬函式的區別

因為父類別的函數可以不做任何操作,所以這裡可以直接等於0;實現純虛擬函式。

//虛擬函式
class Animal{
public:
    virtual void Run(){
        cout<<"Animal->Run"<<endl;
    }
};
//純虛擬函式
class Animal{
public:
    virtual void Run()=0;
};

虛擬函式與純虛擬函式的區別:

純虛擬函式只是一個介面,只能供子類去重寫實現方法。而虛擬函式在裡面也可以去實現父類別的功能。只需要指向父類別的方法即可。

總結:虛擬函式在子類裡面也可以不進行重寫,但純虛擬函式必須在子類去實現,如果把子類中的Run方法去掉,只留下父類別中的純虛擬函式,那麼編譯器會報錯,這裡大家可以試試。

三、動態多型

Animal內部的結構是什麼樣呢?這裡有一個虛擬函式指標(vfptr)和虛擬函式表(vftable)。 指標(vfptr)指向虛擬函式表,在虛擬函式表(vftable)內記錄著虛擬函式的地址,即Run函數的地址。

當子類的Dog去繼承父類別後,父類別的虛擬函式表相應的也繼承下來,子類也會儲存一份和父類別相同的。

注意!這時候如果發生重寫,即子類重寫了父類別的虛擬函式,則子類的虛擬函式表會覆蓋父類別繼承下來的虛擬函式表。但父類別的虛擬函式表不會發生改變。

當父類別的指標或者參照指向子類的物件時,就發生了多型。

下面的程式碼中是指向了Dog,所以會去Dog的虛擬函式表中找到相應的函數,在執行階段發生了動態多型。

    Animal *ani;
    ani = new Dog;
    ani->Run();

到此這篇關於C++淺析虛擬函式使用方法的文章就介紹到這了,更多相關C++虛擬函式內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com