虛函數與純虛函數

1、基本形式:
virtual ReturnType Function_1();            //虛函數聲明
virtual ReturnType Function_2() = 0;      //純虛函數聲明
先講示例吧,再總結結論。

2、示例:
class Animail{
public:
    void Function_1() {cout <<"Animail::Function_1()"<<endl;};
};

class Dog: public Animail{
 public:
     void Function_1() {cout <<"Dog::Function_1()"<<endl;};
};
int main(int argc, char* argv[])
{
    Animail*p = NULL; //定義基類的指針
    Animail cAnimail;
    Dog cDog;

    p = &cAnimail;
    p->Function_1();

 

    p =&cDog;
    p->Function_1();
    return 0;
}

這段代碼的輸出結果是什麼呢?起初我認爲是:Animail::Function_1()與Dog::Function_1(), 因爲第一次輸出是引用基類Animail的實例,第二次輸出是引用子類Dog的實例。事實上答案是Animail::Function_1()與 Animail::Function_1(),爲什麼呢?

這裏我們需要明白:你就記住,不管引用的實例是哪個類的,當你調用的時候,系統會調用左值那個對象所屬類的方法。比如說 上面的代碼類Animail和 Dog都有一個Function_1函數,因爲p是一個Animail類的指針,所以不管你將p指針指向類Animail或是類Dog,最終調用的函數都是類Animail的Function_1函數。這就是靜態聯篇,編譯器在編譯的時候就已經確定好了。可是如果我想實現跟據實例的不同來動態決定調用哪個函數呢?這就須要用到虛函數(也就是動態聯篇)。

class Animail{
public:
    virtual void Function_1() {cout <<"Animail::Function_1()"<<endl;};
};

class Dog: public Animail{
 public:
     virtual void Function_1() {cout <<"Dog::Function_1()"<<endl;};
};

在基類的成員函數前加關鍵字virtual,則表示這個函數是一個虛函數。
所謂虛函數就是在編譯的時候不確定要調用哪個函數,而是動態決定將要調用哪個函數。它的作用就是爲了能讓這個函數在它的子類裏面可以被重載,這樣的話,編譯器就可以使用後期綁定來達到多態了,也就是:用基類的指針來調用子類的這個函數。
要實現虛函數必須保證派生類的函數名與基類相同,參數名參數類型等也要與基類相同。但派生類中的virtual關鍵字可以省略,也表示這是一個虛函數。
下面來分析一下代碼,聲明一個基類的指針(必須是基類,反之則不行)p,把p指向類Animail的實例cAnimail,調用Function_1函數,這時系統會判斷p所指向的實例的類型,如果是Animail類的實例就調用Animail類的Function_1函數,如果是Dog類的實例cDog就調用Dog類的Function_1函數。

下面來講一下純虛函數,包含純虛函數的類也可叫虛基類或者抽象類
class Animail{
public:
    virtual void GetColor()  = 0;
};

class Dog : public Animail{
 public:
     virtual void GetColor() {cout <<"Yellow"endl;};
};

class Pig : public Animail{
public:
 virtual void GetColor() {cout <<"White"<<endl;};
};

如上代碼,定義了一個動物類(Animail),類中有一函數GetColor可取得動物顏色,但動物有很多很多種,顏色自然無法確定,所以就把它聲明爲純虛函數,也就是光聲明函數名不去定義(實現)它,類Dog繼承了Animail並實現了裏面的代碼,返回黃色。Bike類同樣道理。有一點須要注意一下,純虛函數不能實例化,但可以聲明指針,所以上面的main函數中: Animail cAnimail; 編譯器會告訴你:由於它的成員的原因,無法instantiate 抽象類Animail,並且警告你GetColor() 沒有定義。

虛函數
    1, 虛函數是非靜態的、非內聯的成員函數。
    2, 若類中一個成員函數被說明爲虛函數,則該成員函數在派生類中可能有不同的實現。當使用該成員函數操作指針或引用所標識的對象時,對該成員函數調用可採用動態聯編。
    5, 定義了虛函數後,程序中聲明的指向基類的指針就可以指向其派生類。在執行過程中,該函數可以不斷改變它所指向的對象,調用不同版本的成員函數,而且這些動作都是在運行時動態實現的。虛函數充分體現了面向對象程序設計的動態多態性。虛函數充分體現了面向對象程序設計的動態多態性。

純虛函數
    1, 當在基類中不能爲虛函數給出一個有意義的實現時,可以將其聲明爲純虛函數,其實現留待派生類完成。
    2, 純虛函數的作用是爲派生類提供一個一致的接口,它只是個函數的聲明而已,它告訴編譯器,在這個類中的這個純虛函數是沒有函數定義的,該類不能創建對象(即不能實例化),但可以聲明指針,該類的派生類負責給出這個虛函數的重載定義。

發佈了7 篇原創文章 · 獲贊 3 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章