關於父類析構函數爲什麼要定義爲虛函數_第二門課_第一週

喜歡的朋友可以關注收藏一下:  http://blog.csdn.NET/qq_31201973

本文如有錯誤,請及時私信我。

本文解釋了父類析構函數爲什麼要定義爲虛函數的問題。

首先這篇文章要感謝羣裏的  @北京-Qiao 提供了原始的代碼和本文的思路

@北京-Qiao 提供的代碼

#include <iostream>
#include <stdlib.h>
using namespace std;

class base
{
public:
	void fun(){cout << "base" << endl;}
};

class derive:public base
{
public:
	void fun(){cout << "derive" << endl;}
};


int main()
{
	base *p= new derive;
	p->fun();

	system("pause");
	return 0;


}

這個時候父類不是虛函數,輸出結果:

 

//而代碼父類函數變成虛函數以後
class base
{
public:
	virtual void fun(){ cout << "base" << endl; }
	virtual ~base() { cout << "delete base" << endl; }
};


這就和上週文章代碼Shape的數組存放子類對象地址無法訪問子類的情況,而在父類裏寫個虛函數print,子類裏重寫後就可以訪問子類的對象了,這和上面的代碼是一個道理。

 

父類指針new 子類的過程是這樣的

而 static_cast 在父類轉換成子類的時候會保留原類型的特性,導致訪問失敗。數組訪問print虛函數則因爲多態可以訪問到子類的成員,那麼就引出了一個問題析構函數定義爲虛函數的原因。

我們如果delete 父類型的 p 會是這個過程:

那麼delete p 調用析構是隻刪除base p (因爲p實際是棧內存,所以只free(pc)), 沒刪除new derive的空間.

代碼如下(因爲沒有成員我用cout代替):

 

#include <iostream>
#include <stdlib.h>
using namespace std;

class base
{
public:
	virtual void fun(){ cout << "base" << endl; }
	~base() { cout << "delete base" << endl; }
};

class derive :public base
{
public:
	void fun(){ cout << "derive" << endl; }
	~derive() { cout << "delete derive" << endl; }
};


int main()
{
	base *p = new derive;
	p->fun();

	delete p;
	system("pause");
	_CrtDumpMemoryLeaks();
	return 0;
}

輸出結果:

 


改成析構函數改成虛函數後會刪除子類,而刪除子類後,編譯器會自動調用父類的析構函數,刪除父類。

改成虛函數的代碼:

 

class base
{
public:
	virtual void fun(){ cout << "base" << endl; }
	virtual ~base() { cout << "delete base" << endl; }
};

輸出結果:

 


 

  所以析構函數定義爲虛函數是爲了防止內存泄漏。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章