確定基類有虛析構函式

2022-06-23 08:03:12 字數 1971 閱讀 1467

有時,乙個類想跟蹤它有多少個物件存在。乙個簡單的方法是建立乙個靜態類成員來統計物件的個數。這個成員被初始化

為0,在建構函式裡加1,析構函式裡減1。(條款m26裡說明了如何把這種方法封裝起來以便很容易地新增到任何類中,

「my article on counting objects」提供了對這個技術的另外一些改進)

設想在乙個軍事應用程式裡,有乙個表示敵人目標的類:

**class

enemytarget 

enemytarget(

const

enemytarget&) 

~enemytarget() 

static

size_t numberoftargets()

virtual

bool

destroy(); 

//摧毀enemytarget物件後

//返回成功

private

:static

size_t numtargets; 

//物件計數器

};// 類的靜態成員要在類外定義;

// 預設初始化為0

size_t enemytarget::numtargets;

這個類不會為你贏得乙份**防禦合同,它離國防部的要求相差太遠了,但它足以滿足我們這兒說明問題的需要。

敵人的坦克是一種特殊的敵人目標,所以會很自然地想到將它抽象為乙個以公有繼承方式從enemytarget派生出來的類(參

見條款35及m33)。因為不但要關心敵人目標的總數,也要關心敵人坦克的總數,所以和基類一樣,在派生類裡也採用了上

面提到的同樣的技巧:

**class

enemytank: 

public

enemytarget 

enemytank(

const

enemytank

&rhs)

: enemytarget(rhs)

~enemytank() 

static

size_t numberoftanks()

virtual

bool

destroy();

private

:static

size_t numtanks; 

//坦克物件計數器

};(寫完以上兩個類的**後,你就更能夠理解條款m26對這個問題的通用解決方案了。)

最後,假設程式的其他某處用new動態建立了乙個enemytank物件,然後用delete刪除掉:

enemytarget *targetptr = new enemytank;

...delete targetptr;

到此為止所做的一切好象都很正常:兩個類在析構函式裡都對建構函式所做的操作進行了清除;應用程式也顯然沒有錯

誤,用new生成的物件在最後也用delete刪除了。然而這裡卻有很大的問題。程式的行為是不可**的——無法知道將會發

生什麼。

c++語言標準關於這個問題的闡述非常清楚:當通過基類的指標去刪除派生類的物件,而基類又沒有虛析構函式時,結果將

是不可確定的。這意味著編譯器生成的**將會做任何它喜歡的事:重新格式化你的硬碟,給你的老闆發電子郵件,把你

的程式源**傳真給你的對手,無論什麼事都可能發生。(實際執行時經常發生的是,派生類的析構函式永遠不會被調

用。在本例中,這意味著當targetptr 刪除時,enemytank的數量值不會改變,那麼,敵人坦克的數量就是錯的,這對需要高

度依賴精確資訊的部隊來說,會造成什麼後果?)

為了避免這個問題,只需要使enemytarget的析構函式為virtual。宣告析構函式為虛就會帶來你所希望的執行良好的行為:對

象記憶體釋放時,enemytank和enemytarget的析構函式都會被呼叫。

和絕大部分基類一樣,現在enemytarget類包含乙個虛函式。虛函式的目的是讓派生類去定製自己的行為(見條款36),所

以幾乎所有的基類都包含虛函式。

基類虛析構函式

why虛析構函式?主要還是由於基類指標或引用可以不進行顯示型別轉換的情況下指向派生類物件。同時通過引用或者指標或引用呼叫方法時遵循 例如 定義了基類brass,派生類brassplus 如果viewacct 不是虛方法,則b1 ref.viewacct 和b2 ref.viewacct 均是使用br...

基類虛析構函式分析

多型是由虛函式表來實現,通過父類指標來實現動態繫結。子類重寫父類的虛函式後,覆蓋虛函式表中父類該虛函式在表中原來的位置,也許 覆蓋 也就是由此得稱。那析構函式是否也如此呢?程式 中經常可以見到將基類的析構函式寫成虛函式,目的就是為了防止由以下這種情況造成的記憶體洩漏 class a class b ...

多型基類與虛析構函式

假設我們有乙個基類a,很不幸的,a的析構函式是乙個non virtual。同時我們有乙個派生類b,它派生自a。我們定義了乙個a型別指標,它指向的實際物件是b a ptr new b 然後在程式的某處,我們不再需要b了,我們將指標ptr delete掉 delete ptr 注意new永遠要和dele...