天天看點

Pure Virtual Function Call

這裡有詳細的解釋

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下編譯了這個代碼,結果也一樣。

結論

是以,為了避免這個錯誤,您不應該調用析構函數中的函數,調用函數在這個對象中沒有實作的功能。