析構函式(destructor)
也是乙個特殊的成員函式,它的作用與建構函式相反
,它的名字是
類名的前面加乙個「~」符號。
在c++中「~」是位取反運算子,從這點也可以想到,析構函式是與建構函式作用相反的函式。
當物件的生命期結束時,會自動執行析構函式。
具體地說如果出現以下幾種情況,程式就會執行析構函式:
如果在乙個函式中定義了乙個物件(它是自動區域性物件),當這個函式被呼叫結束時,物件應該釋放,在物件釋放前自動執行析構函式。
static區域性物件在函式呼叫結束時物件並不釋放,因此也不呼叫析構函式,只在main函式結束或呼叫exit函式結束程式時,才呼叫static區域性物件的析構函式。
如果定義了乙個全域性物件,則在程式的流程離開其作用域時(如main函式結束或呼叫exit函式) 時,呼叫該全域性物件的析構函式。
如果用new運算子動態地建立了乙個物件,當用delete運算子釋放該物件時,先呼叫該物件的析構函式。
析構函式的作用並不是刪除物件,而是在撤銷物件占用的記憶體之前完成一些清理工作,使這部分記憶體可以被程式分配給新物件使用。程式設計者事先設計好析構函式,以完成所需的功能,只要物件的生命期結束,程式就自動執行析構函式來完成這些工作。
注意:析構函式不返回任何值,沒有函式型別,也沒有函式引數。因此它不能被過載。乙個類可以有多個建構函式,但只能有乙個析構函式。
實際上,析構函式的作用並不僅限於釋放資源方面,它還可以被用來執行「使用者希望在最後一次使用物件之後所執行的任何操作」,例如輸出有關的資訊。這裡說的使用者是指類的設計者,因為,析構函式是在宣告類的時候定義的。也就是說,析構函式可以完成類的設計者所指定的任何操作。
一般情況下,類的設計者應當在宣告類的同時定義析構函式,以指定如何完成「清理」的工作。如果使用者沒有定義析構函式,c++編譯系統會自動生成乙個析構函式,但它只是徒有析構函式的名稱和形式,實際上什麼操作都不進行。想讓析構函式完成任何工作,都必須在定義的析構函式中指定。
【例9.5】包含建構函式和析構函式的c++程式。
#include#include
using
namespace
std;
class
student
//宣告student類
~student( )
//定義析構函式
//輸出有關資訊
void
display( )
//定義成員函式
private
:int
num;
stringname;
char
***;};
int main( )
程式執行結果如下:
constructor called.
(執行stud1的建構函式)
num: 10010
(執行stud1的display函式)
name:wang_li
***: f
constructor called.
(執行stud2的建構函式)
num: 10011
(執行stud2的display函式)
name:zhang_fun
***:m
destructor called. the num is 10011.
(執行stud2的析構函式)
destructor called. the num is 10010.
(執行stud1的析構函式)
c++呼叫建構函式和析構函式的順序
在使用建構函式和析構函式時,需要特別注意對它們的呼叫時間和呼叫順序。在一般情況下,呼叫析構函式的次序正好與呼叫建構函式的次序相反:最先被呼叫的建構函式,其對應的(同一物件中的)析構函式最後被呼叫,而最後被呼叫的建構函式,其對應的析構函式最先被呼叫。如例9.5所示,先執行stud2的析構函式,再執行stu1的析構函式。
可以簡記為:先構造的後析構,後構造的先析構,它相當於乙個棧,先進後出。
但是,並不是在任何情況下都是按這一原則處理的。我們已經介紹過作用域(請檢視:c++區域性變數和全域性變數)和儲存類別(請檢視:c++變數的儲存類別)的概念,這些概念對於物件也是適用的。物件可以在不同的作用域中定義,可以有不同的儲存類別。這些會影響呼叫建構函式和析構函式的時機。
下面歸納一下什麼時候呼叫建構函式和析構函式:
1) 在全域性範圍中定義的物件(即在所有函式之外定義的物件),它的建構函式在檔案中的所有函式(包括main函式)執行之前呼叫。但如果乙個程式中有多個檔案,而不同的檔案中都定義了全域性物件,則這些物件的建構函式的執行順序是不確定的。當main函式執行完畢或呼叫exit函式時(此時程式終止),呼叫析構函式。
2) 如果定義的是區域性自動物件(例如在函式中定義物件),則在建立物件時呼叫其建構函式。如果函式被多次呼叫,則在每次建立物件時都要呼叫建構函式。在函式呼叫結束、物件釋放時先呼叫析構函式。
3) 如果在函式中定義靜態(static )區域性物件,則只在程式第一次呼叫此函式建立物件時呼叫建構函式一次,在呼叫結束時物件並不釋放,因此也不呼叫析構函式,只在main函式結束或呼叫exit函式結束程式時,才呼叫析構函式。
例如,在乙個函式中定義了兩個物件:
void fn()
在呼叫fn函式時,先呼叫stud1的建構函式,再呼叫stud2的建構函式,在fn呼叫結束時,stud1是要釋放的(因為它是自動區域性物件),因此呼叫stud1的析構函式。而stud2 是靜態區域性物件,在fn呼叫結束時並不釋放,因此不呼叫stud2的析構函式。直到程式結束釋放stud2時,才呼叫stud2的析構函式。可以看到stud2是後呼叫建構函式的,但並不先呼叫其析構函式。原因是兩個物件的儲存類別不同、生命週期不同。
C 析構函式 虛析構函式
1.為什麼要定義虛析構函式?如果有乙個帶有虛函式功能的類,則它需要乙個虛析構函式,原因如下 1 如果乙個類有虛函式功能,它經常作為乙個基類使用 2 如果它是乙個基類,它的派生類經常使用new來分配 3 如果乙個派生類物件使用new來分配,並且通過乙個指向它的基類的指標來控制,那麼它經常通過乙個指向它...
C 析構函式和虛析構函式。
析構函式如果不是虛的話,基類的析構函式將不會被呼叫。多型時,也就是派生類被基類指標所指,或者被基類別名 虛析構函式,被呼叫時,其自身的析構函式和基類的析構函式都將會被呼叫。非虛的時候,不進行多型,只有基類的會被呼叫。純虛析構函式 定義的時候除了加 0 還需要給出函式的實現。因為當遞迴的呼叫析構函式時...
C 建構函式 析構函式 虛析構函式
一般地,建立物件和刪除物件時,父類建構函式 子類建構函式 子類析構函式 父類析構函式。特例 如果用new建立了乙個物件,並將父類的指標指向這個子類的物件,那麼用delete撤銷物件時,系統只執行基類的析構函式,而不執行派生類的析構函式。如果希望按照子類析構函式 父類析構函式的順序執行,那麼應該將基類...