關於C++中的虛函數和純虛函數

什麼是虛函數?

定義:在某基類中聲明爲 virtual 並在一個或多個派生類中被重新定 義的成員函數。
用途:實現多態性,通過指向派生類的基類指針,訪問派生類中同名覆蓋成員函數

什麼是純虛函數?

定義:在基類中聲明的虛函數,它在基類中沒有定義,但要求任何派生類都要定義自己的實現方法。在基類中實現純虛函數的方法是在函數原型後加"=0"。

用途:爲了方便使用多態特性,嚐嚐需要在基類中定義虛擬函數;在很多情況下,基類本身生成對象是不合情理的。例如,動物作爲一個基類可以派生出老虎、孔雀等子類,但動物本身生成對象明顯不合常理。

什麼是抽象類?

定義:包含純虛函數的類稱爲抽象類。由於抽象類包含了沒有定義的純虛函數,所以不能定義抽象類的對象。

用途:將有關的操作作爲結果接口組織在一個繼承層次結構中,由它來爲派生類提供一個公共的根,派生類將具體實現在其基類中作爲接口的操作。所以派生類實際上刻畫了一組子類的操作接口的通用語義,這些語義也傳給子類,子類可以具體實現這些語義,也可以再將這些語義傳給自己的子類。

什麼是動態綁定?

動態綁定(動態聯編、推遲聯編):聲明基類的指針,利用該指針指向任意一個子類對象,調用相應的虛函數。由於編寫代碼的時候並不能確定被調用的是基類的函數還是派生類的函數,所以被稱爲“虛函數”,即一個類函數的調用並不是在編譯時刻被確定的,而是在運行時刻被確定的。如果沒有使用虛函數的話,即沒有利用C++多態性,則利用基類指針調用相應的函數的時候,將總被限制在基類函數本身,而無法調用到子類中被重寫過的函數。

其他

(0) C++多態(polymorphism)是通過虛函數來實現的,虛函數允許子類重新定義成員函數,而子類重新定義父類的做法稱爲覆蓋(override),稱爲重寫。

(1) 如果未聲明爲虛函數,企圖通過基類指針調用派生類的非虛函數是不行的。

(2) C++規定,當一個成員函數被聲明爲虛函數時,其派生類中的同名函數都自動成爲虛函數。因此在派生類重新聲明該虛函數時,可以加virtual,也可以不加,但習慣上一般在每一層聲明該函數時都加virtual,使程序更加清晰。

(3) 如果在派生類中沒有對基類的虛函數重新定義,則派生類簡單地繼承其直接基類的虛函數。

(4) 聲明純虛函數的類是一個抽象類,這樣的類不允許實例化。定義純虛函數是爲了實現一個接口,起到一個規範的作用,規範繼承這個類的派生類必須實現這個函數,否則編譯無法通過。

代碼如下:

#include<iostream>
using namespace std;

// 抽象類,無法實例化
class test2
{
public:
    // 純虛函數
    virtual void fun2() = 0;
};

// 繼承抽象類,重寫父類虛函數
class B :public test2
{
public:
    virtual void fun2()
    {
        cout << "fun2" << endl;
    }
};

class test
{
public:
    // 虛函數
    virtual void fun()
    {
        cout << "virtual class test" << endl;
    }
};

class A:public test
{
public:
    // 重寫父類的虛函數
    void fun()
    {
        cout << "virtual class A" << endl;
    }
};

int main() 
{
    // 多態:父類指針指向子類對象
    shared_ptr<test> t1 = make_shared<A>();
    t1->fun();

    // 父類指針指向自身
    t1 = make_shared<test>();
    t1->fun();

    // 子類實現父類的純虛函數
    B b;
    b.fun2();
    return 0;
}

運行結果:

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