建構函式 析構函式和虛函式的關係

2021-09-06 10:25:09 字數 1048 閱讀 9576

首先明確兩點

建構函式不可能定義為虛函式

虛函式的目的是通過父類引用或者指標呼叫子類的成員函式。而建構函式的目的是建立物件。建立子類物件時,將呼叫子類的建構函式,而不是父類的建構函式。子類的建構函式將使用父類的乙個建構函式。這種順序不同於繼承機制。因此,子類不繼承父類的建構函式,所以將類的建構函式宣告為虛函式沒有意義。這個如果不能理解,記住就好了。

父類的析構函式應該是虛函式

關於第二點,舉個例子

a是父類,b是a的子類,在b中還新增了乙個char* name成員,name指向一塊由new申請的記憶體。當b類的物件被銷毀是,必然會呼叫~b()析構函式來釋放記憶體。請看下面**:

a* a = new b;

...delete a; //此時呼叫哪個析構函式,~a()還是~b();

如果,a 的析構函式沒有宣告為虛函式,那麼delete a使用預設的靜態聯編,也就是呼叫a的析構函式~a();這將會釋放掉b類中a部分指向的記憶體,但是不會釋放新的類成員指向的記憶體,也就是b的name成員指向的記憶體塊,這樣就造成記憶體洩漏的問題。但是如果a的析構函式宣告為虛函式,那麼b的虛函式表中會把指向a的析構函式的指標位置改為指向b的析構函式。此時呼叫delete a就會呼叫b的析構函式,釋放掉由b指向的記憶體,然後呼叫a的析構函式,釋放由a指向的記憶體。

空口無憑,來個例子看看再說。

#includeusing namespace std;

class a {

public:

~a() {

cout<<"a::~a()"《這段**執行結果:

a::~a()

可見僅僅執行了a的析構函式,釋放掉了a指向的記憶體,但是b指向的記憶體沒有被釋放掉。

我們把a的析構函式宣告為虛函式

virtual ~a() {

cout<<"a::~a()"《再次執行,結果如下:

b::~b()

a::~a()

程式先呼叫子類的析構函式,釋放掉b指向的記憶體,然後呼叫父類的析構函式,釋放掉a指向的記憶體。

C 析構函式 建構函式 虛函式關係

析構函式 destructor 也是乙個特殊的成員函式,它的作用與建構函式相反,它的名字是類名的前面加乙個 符號。在c 中 是位取反運算子,從這點也可以想到 析構函式是與建構函式作用相反的函式。當物件的生命期結束時,會自動執行析構函式。具體地說如果出現以下幾種情況,程式就會執行析構函式 如果在乙個函...

建構函式 析構函式 虛析構函式

說析構函式之前,先說下建構函式。建構函式用來完成對物件的一系列初始化操作,主要作用有 1.給建立的物件建立乙個識別符號 2.為物件資料成員開闢記憶體空間 3.完成物件資料成員的初始化 當並未顯示的定義建構函式時,會生成乙個預設的建構函式,預設建構函式不能完成物件資料成員的初始化,只能給物件建立一識別...

關於建構函式 析構函式和虛函式的關係

建構函式不能宣告為虛函式的原因是 解釋一 所謂虛函式就是多型情況下只執行乙個,而從繼承的概念來講,總是要先構造父類物件,然後才能是子類物件,如果建構函式設為虛函式,那麼當你在構造父類的建構函式時就不得不顯示的呼叫構造,還有乙個原因就是為了防錯,試想如果你在子類中一不小心重寫了個跟父類建構函式一樣的函...