探討虛擬函式與純虛擬函式的區別
轉載請註明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、成員函式是靜態繫結