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...