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

2022-07-26 18:48:12 字數 2947 閱讀 1218

析構函式(destructor)也是乙個特殊的成員函式,它的作用與建構函式相反,它的名字是類名的前面加乙個「~」符號。

在c++中「~」是位取反運算子,從這點也可以想到:析構函式是與建構函式作用相反的函式。當物件的生命期結束時,會自動執行析構函式。

具體地說如果出現以下幾種情況,程式就會執行析構函式:

①如果在乙個函式中定義了乙個物件(它是自動區域性物件),當這個函式被呼叫結束時,物件應該釋放,在物件釋放前自動執行析構函式。

②static區域性物件在函式呼叫結束時物件並不釋放,因此也不呼叫析構函式,只在main函式結束或呼叫exit函式結束程式時,才呼叫static區域性物件的析構函式。

#include #include 

using

namespace

std;

class

box box(

int h=10,int w=12,int len=3

):height(h),width(w),length(len){}

intvolume();

private

:

intheight;

intwidth;

intlength;

};int

box::volume()

intmain()

; cout

<

the volume a[0] is

"<0].volume()<

cout

<

the volume a[1] is

"<1].volume()<

//system("pause");

return0;

}

執行結果:

如果執行注釋的那行,結果又是如何??自己去嘗試一下!!

③如果定義了乙個全域性物件,則在程式的流程離開其作用域時(如main函式結束或呼叫exit函式) 時,呼叫該全域性物件的析構函式。

乙個很典型的例子:

#include #include 

#include

using

namespace

std;

class

cdemo

;cdemo::cdemo(

const

char*str)

cdemo::~cdemo()

void

func()

static cdemo globleobject("

globeobject");

intmain()

根據**資料型別大致分為三個部分:靜態全域性變數(static cdemo globleobject),靜態區域性變數(static cdemo staticobject),普通區域性變數(cdemo localobjectinmain.....);

1、由於靜態全域性物件的建構函式將在main函式之前執行,則析構在main函式之後執行

2、函式內部的static物件的建構函式將在第一次呼叫該函式時呼叫,main函式結束之後執行。但其析構會在全域性物件之前,因為所有物件的析構順序和構造順序相反,即全域性物件在函式內部的static物件前構造,在後面析構。若包含靜態區域性物件的函式未被呼叫,則也不進行析構

其執行結果:

此**有個小問題就是當執行注釋的那一行時,結果又會不一樣(估計是vc和標準c++之間的區別吧!!)

④如果用new運算子動態地建立了乙個物件,當用delete運算子釋放該物件時,先呼叫該物件的析構函式。

#include using

namespace

std;

class

a ~a()

};class b :public

a ~b()

};int

main()

**分析:1、大家都知道建構函式裡就可以呼叫成員變數,而繼承中子類是把基類的成員變成自己的成員,那麼也就是說子類在建構函式裡就可以呼叫基類的成員了,這就說明建立子類的時候必須先呼叫基類的建構函式,只有這樣子類才能在建構函式裡使用基類的成員,所以是建立子類時先呼叫基類的建構函式然後再呼叫自己的建構函式。通俗點說,你要用某些物品,但這些物品你沒辦法自己生產,自然就要等別人生產出來,你才能拿來用。

2、接著就是析構函式了,上面說到子類是將基類的成員變成自己的成員,那麼基類就會只存在子類中直到子類呼叫析構函式後,做個假設:假如在基類的析構函式呼叫比子類的先,這樣會發生什麼事呢?類成員終止了,而類本身卻還在,但是在類存在的情況下,類成員就應該還存在的,這不就產生矛盾了嗎?所以子類是呼叫自身的析構函式再呼叫基類的析構函式。

執行結果: a...

b...

~a...

修改一下以上**:

#include using

namespace

std;

class

a

virtual ~a()

};class b :public

a ~b()

};int

main()

執行結果:a...

b...

~b...

~a那麼這是為什麼呢??也許delete並不是那麼傻,她會去虛函式表裡面檢視當前析構函式是否被定義為虛函式,如果是虛函式,它就會想了,那物件會不會例項化的是子類的物件呢,於是再判斷是否例項化為子類物件,如果是就先呼叫子類的析構函式

總結:析構函式的作用並不是刪除物件,而是在撤銷物件占用的記憶體之前完成一些清理工作,使這部分記憶體可以被程式分配給新物件使用。程式設計者事先設計好析構函式,以完成所需的功能,只要物件的生命期結束,程式就自動執行析構函式來完成這些工作。

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

一般地,建立物件和刪除物件時,父類建構函式 子類建構函式 子類析構函式 父類析構函式。特例 如果用new建立了乙個物件,並將父類的指標指向這個子類的物件,那麼用delete撤銷物件時,系統只執行基類的析構函式,而不執行派生類的析構函式。如果希望按照子類析構函式 父類析構函式的順序執行,那麼應該將基類...

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

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

建構函式 析構函式 虛函式

在類中,建構函式用於初始化物件及相關操作。建構函式是不能宣告為虛函式的,因為虛函式對應乙個virtual table 虛函式表 這個表的位址是儲存在物件的記憶體空間的。而在執行建構函式前,物件尚未完成建立,記憶體都沒有被分配,所以無法去查詢虛函式表,它不存在,因此也就無法得知該呼叫哪乙個函式了。析構...