深度分析c 解構函式的作用,深度分析C 解構函式的作用

時間 2021-12-28 21:35:57

1樓:匿名使用者

這樣的問題, 有一個最實用的方法, 就是去跟一下彙編的**, 當然了這需要你懂一點點的組合語言.

問題的原因就是: 當你呼叫基類的解構函式d.base::

~base()時, c++會先把d物件中的虛擬函式表改變一下, 原來指向derived類的虛擬函式表, 現在指向base類的虛擬函式表. 彙編**為:

004116e3 mov eax,dword ptr [this]

004116e6 mov dword ptr [eax],offset base::`vftable'

這裡就把base的vtable給物件d了.

至於為什麼c++要這麼處理, 一樓的基本上說出來了, 就是在建構函式和解構函式裡多型性是被凍結了的, 在這兩個函式中沒有多多型性.

具體說明如下:在構造或者解構函式中呼叫沒有實現的純虛擬函式是很恐怖的,但是一般這個動作編譯器都能檢查出來;但是如果中間隔了一層(建構函式呼叫非純虛擬函式a,而a呼叫了純虛擬函式),編譯器就無能為力了,然後就等著執行時錯誤出現吧~~~

而且,在建構函式或解構函式的上下文中,虛擬函式是沒有意義的,它只呼叫本類的那個函式。因為,就建構函式來說,基類的建構函式總是先呼叫,而根據前面所說的,基類的建構函式中會被編譯器插入一些填寫本型別虛擬函式表的**,也就是在執行基類建構函式中的使用者**時,此時虛擬函式表中的儲存的僅是本型別的虛擬函式地址。也就是在構造時,多型是被freeze的。

對應解構函式則是相反的過程,原理是一樣的

至於解構函式還執行其它什麼任務了, 我帖出來這段的彙編**你就知道了:

~base()

00411db4 pop edi

00411db5 pop esi

00411db6 pop ebx

00411db7 add esp,0cch

00411dbd cmp ebp,esp

00411dbf call @ilt+460(__rtc_checkesp) (4111d1h)

00411dc4 mov esp,ebp

00411dc6 pop ebp

00411dc7 ret

說實話, 除了你碰到的這個問題, 還真是沒有其它什麼值得你注意的問題了.

不知道這麼說, 你明白了沒有. 有問題的話你可以再補充問題

2樓:風落翎

哇,這什麼學校,講得好詳細啊,這個都考。

解構函式開始之前,要把虛擬函式表改成本類的虛擬函式表。確保在解構函式中呼叫的virtual成員是本類的。因為這時子類的解構函式已經執行過了,子類那部分資料已不再可用。

解構函式開始執行到你的**時,該物件就變成一個基類物件繼續析構了。

你的**之後,析構成員,析構基類子物件。

3樓:匿名使用者

建構函式 為類分配記憶體

解構函式 為類釋放記憶體,包括虛擬函式表

4樓:匿名使用者

虛擬函式表不可能變化的,對於每一個例項來講,他儲存的僅僅只是一個指向虛擬函式表的指標(虛擬函式表每個類只有一份,和類的相關資料放在一塊兒)。。所以你顯式地呼叫父類解構函式後,虛擬函式表沒有被破壞,被破壞的只是例項物件的那個虛擬函式表指標。我們可以做個試驗,:

void showint(void *p, int size)

注意我是在你**基礎上改的,加了個函式showint,main也做了些修改

執行結果:

14710868

123**********====

derived::f()

**********====

1471110812

the base's destructor func called.

1471086812

**********====

base::f()

press any key to continue . . .

****************************

可以看到,第一行我加的一個base物件的虛擬函式表在14710868處

而後來可以看到,一個子類derived的虛擬函式表在14711108處

單呼叫了解構函式後,該指標卻被指向了父類虛擬函式表14710868處

*****====

事實上程式設計師一般不應該顯式地呼叫解構函式的,你這樣呼叫了照成了程式行為未定義,虛擬函式表指標被破壞也就不足為奇了。。

*****

樓主要還想知道為什麼會被破壞,我個人倒沒研究過到這一層,不過還是有路子的:1、看侯捷那本《深入理解c++物件模型》掌握c++物件模型的理論知識; 2、然後閱讀編譯器產生的彙編**(gcc的話加-s開關,微軟的編譯器在工程選項裡面有對應項)

c解構函式何時呼叫,C 解構函式何時呼叫

建構函式是建立的時候也就是new的時候呼叫,析構是釋放也就是delete的時候呼叫,你new的話應該是呼叫建構函式 也就是 date date int i 程式第39行,people的建構函式裡面有一行date birthday 1 建立了一個date類的臨時變數。當函式退出的時候,這個變數也會被撤...

解構函式的呼叫,解構函式在何時呼叫

在vc中除錯的話,你可以主動刪除物件,這樣就會呼叫解構函式int main 修改為int main 如樓上所說,如果你的程式視窗是在程式執行後立即關閉的話,你肯定看不到呼叫解構函式的資訊.因為解構函式的呼叫是在main結束後,也就是system pause 執行後,而不是你想像的那樣先呼叫,然後再執...

c中建構函式與解構函式的問題,C 中建構函式與解構函式的問題

你的getname函式在 你的類定義中只有getscore和getid c 關於建構函式和解構函式呼叫次數的問題 沒問題啊。引數傳遞的時候第一次拷貝構造呼叫,在函式返回的時候賦值給c2 再次呼叫了拷貝構造。析構的話 c1 c2 c 三次 傳遞引數和返回引數各一次拷貝建構函式,所以是2次 有兩個物件c...