探討虛函數與純虛函數的區別

轉載請註明t1234xy4原創:http://blog.csdn.net/t1234xy4/article/details/51191270
《C++ Primer》書上學習得到的基礎:
純虛函數:
1、純虛函數只聲明,沒有定義。書寫=0說明爲純虛函數。
2、含有純虛函數的內,稱爲抽象基類,所謂抽象基類只負責定義接口,後續的其他類可以覆蓋該接口,我們不能創建抽象基類的實例。
3、能夠被覆蓋。

普通虛函數:
1、聲明爲普通函數前加virtual,不僅要申明,而且必須定義。
2、能夠被覆蓋。(只有虛函數能夠被覆蓋)

測試虛函數與純虛函數區別:
測試1、測試純虛函數能不能有重名而函數個數不同的重載:
//virtualBase.hxx:

#include <string>
#include <iostream>
#pragma once
using namespace std;
class VirtualBase
{
public:
    VirtualBase(void);
    virtual void  helloword(string s)=0;
    virtual void helloword(string s1,string s2)=0;
    ~VirtualBase(void);
};

virtualclass 繼承了virtualBase

VirtualClass.hxx :

#pragma once
#include "virtualbase.h"
#include "VirtualBaseCopy.h"
class VirtualClass :
    public VirtualBase/*,public VirtualBaseCopy*/
{
public:
    VirtualClass(void);
    virtual void helloword(string s);
    virtual void helloword(string s1,string s2);
    ~VirtualClass(void);
};

virtualclass.c

#include "StdAfx.h"
#include "VirtualClass.h"

void VirtualClass::helloword(string s1,string s2)
{
    cout << "VirtualClass: hello ,"<<s1 <<","<<s2<<endl;
}
void VirtualClass::helloword(string s)
{
    cout << "virtualclass: hello,"<<s<<endl;
}

Main.c:

int _tmain(int argc, _TCHAR* argv[])
{
    **VirtualBase *base = new VirtualClass; //注意此處**
    string s = "jack";
    string s2 = "rose";
    base->helloword(s,s2);
    base->helloword(s);
    while (1){}
    return 0;
}

執行結果如下:
這裏寫圖片描述
測試1結論:如果基類擁有重載純虛函數接口,子類分別實例化後可用。也就是說,子類重寫的兩個函數分別覆蓋了基類的兩個函數。

測試2:如果基類VirtualBase中只有其中一個接口?,子類中是否可以出現同名的函數。
修改VirtualBase.hxx如下:

#include <string>
#include <iostream>
#pragma once
using namespace std;
class VirtualBase
{
public:
    VirtualBase(void);
    //virtual void  helloword(string s)=0;
    virtual void helloword(string s1,string s2)=0;
    ~VirtualBase(void);
};
int _tmain(int argc, _TCHAR* argv[])
{
    **VirtualClass *base = new VirtualClass;**//注意此處
    string s = "jack";
    string s2 = "rose";
    base->helloword(s,s2);
    base->helloword(s);
    //cout<<base->add(2,3);
    while (1){}
    return 0;
}

結果:
這裏寫圖片描述

修改爲下面的後:

**VirtualBase *base = new VirtualClass;**//注意此處

編譯不通過。
測試2結論:
1、編譯不通過在情理之中,基類的指針開闢的空間結構不具有另一個函數的指針。
2、helloword(string s1,string s2)是VirtualClass的虛函數可行,運行沒有問題。也就是說,子類可以出現與父類接口同名的函數。

虛函數是可以連續繼承的。也就是說,一個函數在基類中爲虛函數,那麼在他的子子孫孫類中都是虛函數。

測試3: VirtualClass的子類還能否夠繼承他
我們添加類VirtualConcreate繼承VirtualClass類,並重寫虛函數helloword(string s):

void VirtualConcreate::helloword(string s)
{
    cout<<"concrete:hello,"<<s<<endl;
}

實例化如下:

**VirtualBase *base = new VirtualConcreate;**

結果如下:
這裏寫圖片描述

測試3結論如下:
1、如果在VirtualConcrete類中,函數中重寫了父類的虛函數,那麼父類的虛函數將被覆蓋掉;
2、子類中沒有重寫的父類函數,直接調用父類函數;

測試4:基類的接口,在其派生類中出現了與接口同名(函數個數不同或者參數不同)的虛函數是否一起被繼承。
這裏寫圖片描述
測試4結論:可以一起被繼承。

測試總結:虛函數也可用重載,純虛函數一樣可以重載。,只有形參類型完全相同的虛函數纔會被覆蓋!!

測試5:普通成員函數與虛函數區別。
虛函數:
1、只有虛函數才能被覆蓋(《C++ primer(第5版)》 538頁)
2、虛函數是動態綁定

成員函數:
1、成員函數是靜態綁定

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