為什麼建構函式不能是虛函式而析構函式可以

2021-07-11 00:59:32 字數 1327 閱讀 7269

首先,虛函式的實現原理是:在定義具有虛函式的類或者繼承類的繼承的時候,會相應建立乙個虛函式表vtable,即每個類都對應乙個需函式表,而在定義類的物件的時候,每個物件都會有乙個指向相應類的虛表指標vptr,vptr指向虛表的入口位址,在呼叫相應的虛函式的時候,根據該入口位址尋找對應的函式。

對於建構函式,其作用是在物件例項化的時候自動呼叫,對該物件進行初始化操作。前述中提到,虛函式是通過vptr來呼叫的,而呼叫建構函式的時候例項化並未完成,也就是說此時並不存在vptr,因而,無法使用vptr來呼叫建構函式。

另一方面,虛函式的呼叫是虛呼叫,通過在執行時查詢虛函式表得到具體函式入口位址,相當於只需要有部分資訊就可以呼叫該函式。然而定義具體類的物件的時候,需要明確指定物件型別,而且在定義子類物件的時候首先呼叫的是父類的建構函式然後才是呼叫子類建構函式,如果使用了虛函式,那麼僅僅是呼叫子類建構函式並不能完成物件的初始化。

而對於析構函式,則需要定義為虛析構函式,防止記憶體洩露的發生。

如下**:

#include 

class

a; ~a()

};class

b:public

a; ~b()

};int main()

此時的輸出為:

construct a

construct b

b has been destructed!

a has been destructed!

也就是對於普通的定義子類物件然後析構該物件的行為,其首先是呼叫子類的析構函式,然後再呼叫父類的析構函式,因為在定義子類物件的時候,首先是呼叫了父類物件的建構函式,然後才是呼叫子類的建構函式,那麼子類物件中包含了父類的資訊,析構的時候也必然需要呼叫父類的析構函式。

而如果使用父類的指標指向子類的物件:

int main()

此時的輸出是

construct a

construct b

a has been constructe!

此時僅僅是呼叫了父類的析構函式,因為指標型別是父類的。此時會造成的後果是,儲存子類資訊的那部分記憶體空間沒有被析構,導致記憶體洩露。

如果將析構函式定義成虛函式,那麼輸出的時候則和普通定義的子類的物件析構一樣,輸出為:

construct a

construct b

b has been destructed!

a has been destructed!

此時的析構行為才是正確的,即先呼叫子類析構函式,再呼叫父類析構函式。

析構函式為什麼是虛函式而建構函式不行

1,從儲存空間角度 虛函式對應乙個vtable,這大家都知道,可是這個vtable其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,無法找到vtable,所以建構函式不能是虛函式。2,從使用角度 虛函式主要用...

建構函式為什麼不能是虛函式

1.從儲存空間角度,虛函式對應乙個指向vtable虛函式表的指標,這大家都知道,可是這個指向vtable的指標其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,怎麼找vtable呢?所以建構函式不能是虛函式。...

建構函式為什麼不能是虛函式

1.從 儲存空間角度,虛函式對應乙個指向vtable虛函式表的指標,這大家都知道,可是這個指向vtable的指標其實是儲存在物件的記憶體空間的。問題出來了,如果建構函式是虛的,就需要通過 vtable來呼叫,可是物件還沒有例項化,也就是記憶體空間還沒有,怎麼找vtable呢?所以建構函式不能是虛函式...