1. 程式人生 > >問題十五:C++中抽象類,虛擬函式是什麼鬼?怎麼測試

問題十五:C++中抽象類,虛擬函式是什麼鬼?怎麼測試

該篇內容提要:

1,理論解釋,來自網上;

15.1 抽象類、虛擬函式是什麼鬼?

一、純虛擬函式定義.
     
純虛擬函式是在基類中宣告的虛擬函式,它在基類中沒有定義,但要求任何派生類都要定義自己的實現方法。在基類中實現純虛擬函式的方法是在函式原型後加“=0”

二、引入原因:
1
、為了方便使用多型特性,我們常常需要在基類中定義虛擬函式。
2
、在很多情況下,基類本身生成物件是不合情理的。例如,動物作為一個基類可以派生出老虎、孔雀等子類,但動物本身生成物件明顯不合常理。為了解決上述問題,引入了純虛擬函式的概念,將函式定義為純虛擬函式(方法:virtual ReturnType Function()= 0;

),則編譯器要求在派生類中必須予以過載以實現多型性。同時含有純虛擬函式的類稱為抽象類,它不能生成物件。這樣就很好地解決了上述兩個問題。三、相似概念:
1
、多型性指相同物件收到不同訊息或不同物件收到相同訊息時產生不同的實現動作。C++支援兩種多型性:編譯時多型性,執行時多型性。
    a.
編譯時多型性:通過函式過載和運算子過載來實現的。
    b
執行時多型性:通過繼承和虛擬函式來實現的。
2
、虛擬函式虛擬函式是在基類中被宣告為virtual,並在派生類中重新定義的成員函式,可實現成員函式的動態過載純虛擬函式的宣告有著特殊的語法格式:virtual 返回值型別成員函式名(引數表)=0

請注意,純虛擬函式應該只有宣告,沒有具體的定義,即使給出了純虛擬函式的定義也會被編譯器忽略。

3抽象類

包含純虛擬函式的類稱為抽象類。由於抽象類包含了沒有定義的純虛擬函式,所以不能定義抽象類的物件。C++中,我們可以把只能用於被繼承而不能直接建立物件的類設定為抽象類(Abstract Class)。

之所以要存在抽象類,最主要是因為它具有不確定因素。我們把那些類中的確存在,但是在父類中無法確定具體實現的成員函式稱為純虛擬函式。純虛擬函式是一種特殊的虛擬函式,它只有宣告,沒有具體的定義。抽象類中至少存在一個純虛擬函式;存在純虛擬函式的類一定是抽象類。存在純虛擬函式是成為抽象類的充要條件

15.2測試兩個子類對父類虛擬函式的實現

父類(抽象類,包含虛擬函式):test_base

test_base.h

#ifndefTEST_BASE_H

#defineTEST_BASE_H

classtest_base

{

    public:

//      test_base() {}             /*抽象類不需要建構函式,因為他不會有物件*/

        virtual void vfb() = 0;/*虛擬函式的宣告:“virtual+普通函式宣告方式+=0*/

};

#endif //TEST_BASE_H

----------------------------------------------test_base.cpp----------------------------------------------

test_base.cpp為空

子類(繼承抽象類,必須實現父類的虛擬函式):test_extend1和test_extend2

#ifndefTEST_EXTEND1_H

#defineTEST_EXTEND1_H

#include<test_base.h>

classtest_extend1 : public test_base

{

    public:

        test_extend1() {}  /*這個一定要有,不能寫成“test_extend1();*/

        virtual void vfb(); /*子類中宣告虛擬函式:“virtual+普通函式宣告方式。注意此處沒有“=0*/

};

#endif //TEST_EXTEND1_H

test_extend1.cpp

#include"test_extend1.h"

#include<iostream>

usingnamespace std;

void test_extend1::vfb()

{

/*特別注意:子類對虛擬函式的實現要放在.cpp(不能放在.h中)。為什麼?原因不詳。但是如果放在.h編譯時會報“multiple definition”的錯誤(搞不清為什麼,不同子類對其實現時會報這樣的錯誤,藍瘦,香菇)*/

    std::cout <<"test_extend1::vfb()" << endl;

}

----------------------------------------------test_extend2.h--------------------------------------------

test_extend2.h

#ifndefTEST_EXTEND2_H

#defineTEST_EXTEND2_H

#include<test_base.h>

classtest_extend2 : public test_base

{

    public:

        test_extend2() {} 

        virtual void vfb();

};

test_extend2.cpp

#include"test_extend2.h"

#include<iostream>

usingnamespace std;

void test_extend2::vfb()

{

    std::cout <<"test_extend2::vfb()" << endl;

}

----------------------------------------------main.cpp------------------------------------------

main.cpp

    #include"test_extend1.h"

    #include "test_extend2.h"

    int main(){

        test_base *te1 = new test_extend1();

        test_base *te2 = new test_extend2();/*新建子類物件*/

        te1->vfb();

                   te2->vfb(); /*呼叫子類實現的父類的虛擬函式*/

        return 0;

}

輸出結果: