1. 程式人生 > >探討虛擬函式與純虛擬函式的區別

探討虛擬函式與純虛擬函式的區別

轉載請註明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、成員函式是靜態繫結