這裡有詳細的解釋
https://www.codeproject.com/Articles/14879/Pure-Virtual-Function-Call
當一個對象包含一個純虛函數(一個未實作的函數)時,這個對象根本不能被構造,是以純虛函數不能被稱為全部。試試下面的代碼:
class Parent {
public:
Parent() {
}
~Parent() {
ClearALL();
}
void ClearALL() {
ThePure();
}
virtual bool ThePure() = 0 ;
}
;
void main() {
Parent P;
/*error C2259: 'Parent' : cannot instantiate abstract class due to following members: Parent::ThePure(void)*/
}
等等……可以做到…
那麼,一個純虛函數是如何被調用的呢?為了生産它,讓我們繼續工作,從父類繼承一個新的類。我們叫它孩子吧。是以,我們有以下代碼:
class Parent {
public:
Parent() {
}
~Parent() {
ClearALL();
}
void ClearALL() {
ThePure();
}
virtual bool ThePure() = 0 ;
}
;
class Child : public Parent {
public:
Child() {
}
~Child() {
}
/* The implementation of the pure virtual function */
virtual bool ThePure() {
return true;
}
}
;
void main() {
Child c;
}
現在,我們對我們所做的多态性很滿意,然後運作我們的程式,然後得到“純虛拟函數調用”的震撼。
為了分析這一點,讓我們假設一個純虛函數。調用該函數thepure()但版本,沒有實作我們應該從父類别對象并調用函數把它像:
Parent P;
P.ThePure(); //Compilation Error!
這當然是不可能的,但等等,這是可能的。怎麼用????
我們都知道從面向對象的概念來看,當一個對象被破壞時,它被稱為析構函數,然後是它的父類的析構函數等等,直到我們到達該家族的第一個父節點,然後銷毀過程就完成了。是以,如果您檢查了上面的代碼,就會看到在父析構函數中,我們調用一個函數,函數反過來調用一個純虛函數。在父代碼中寫這是合法的,因為在運作時不可能有它的執行個體。當然,代碼将運作在類型子對象中(因為父代不能完全按照我們所說的構造)。但是此時(父析構函數内部)被調用并完成了子析構函數,是以,我們現在沒有一個類型子對象,但是目前對象(隻被破壞)是類型父類,是以析構函數中的所有調用都是對這個對象中函數的調用。是以,可以得到純虛函數。
編譯器有時會有幫助
現在,你要問上面的代碼的問題是,為什麼我不叫純虛函數直接與其說clearall()反過來調用它的析構函數。答案是幸福的消息。編譯器很聰明,可以檢測出這樣的錯誤(為什麼?)并發對外連結接錯誤。但是如果像這樣間接調用它,編譯器将對調用鍊中的函數視而不見,獲得純虛函數。
我在vc++ 6和vc++ 2003下編譯了這個代碼,結果也一樣。
結論
是以,為了避免這個錯誤,您不應該調用析構函數中的函數,調用函數在這個對象中沒有實作的功能。