先看第一種最簡單的情形,所有類中沒有任何虛函式的菱形繼承。
下面是c++原始碼:
class top讓我們來看看,彙編**裡面是怎樣的情形,先看main函式裡面的彙編碼:};class left : public
virtual
top
};class right : public
virtual
top
};class bottom : public left, public
right
};int
main() ;
;接下來是bottom建構函式的彙編碼:33 : int main() ;
xoreax, eax
movesp, ebp
popebp
ret0
_main endp
??0bottom@@qae@hhhh@z proc ;下面是left建構函式的彙編碼:bottom::bottom, comdat
;_this$ = ecx
;28 : bottom(int ll, int jj, int kk, int ii) : top(ii), left(jj, ii), right(kk, ii)
moveax, dword ptr _this$[ebp]
movesp, ebp
popebp
ret20
;00000014h
??0bottom@@qae@hhhh@z endp
??0left@@qae@hh@z proc ;下面是right建構函式的彙編碼:left::left, comdat
;_this$ = ecx
;12 : left(int jj, int ii) : top(ii)
moveax, dword ptr _this$[ebp]
movesp, ebp
popebp
ret12
;0000000ch
??0left@@qae@hh@z endp
??0right@@qae@hh@z proc ;下面是top函式的彙編碼:right::right, comdat
;_this$ = ecx
;20 : right(int kk, int ii) : top(ii)
moveax, dword ptr _this$[ebp]
movesp, ebp
popebp
ret12
;0000000ch
??0right@@qae@hh@z endp
??0top@@qae@h@z proc ;下面是類之間的繼承關係圖:top::top, comdat
;_this$ = ecx
;4 : top(int ii)
moveax, dword ptr _this$[ebp]
movesp, ebp
popebp
ret4
??0top@@qae@h@z endp
圖1 菱形繼承,所有類不含任何虛函式
下面是每個類的記憶體布局
上面**中,left和right類物件首位址處都含有乙個vbtable(誤寫為了vtable)指標,指向乙個vb
table,vbtable裡面只有兩項:第一項是vbtable指標所屬類的虛表指標vptr(沒有就從物件首位址開始算)相對於vbtale指標的偏移量;第二項是其父類虛表指標vptr(沒有的話就是物件首位址)相對於vbtable的偏移量。
從bottom left right的建構函式可以看出來,在每次呼叫相應的建構函式之前,都會有編譯器傳入乙個標誌,以此來防止虛基類建構函式被多次呼叫。這就是為什麼虛基類只有乙份例項的原因。虛基類的建構函式總是由當前正構造的物件的構造函式呼叫,比如這裡構造bottom物件時,就由bottom
構造函式呼叫,left和right建構函式不會呼叫。
從彙編看c 的虛擬繼承以及其記憶體布局 一
先看第一種最簡單的情形,所有類中沒有任何虛函式的菱形繼承。下面是c 原始碼 class top class left public virtual top class right public virtual top class bottom public left,public right int...
從類的記憶體結構看C 繼承
先看下面這個簡單的例子,我們建立乙個基類 base class 通過簡單的繼承 inherit 產生兩個派生類 derived class 然後通過乙個基類的指標去呼叫這兩個派生類,並且呼叫類中的函式。class base void show2 class derived1 public base ...
從彙編的眼光看C (之delete記憶體洩露)
有過c語言程式設計的朋友大多知道,如果在malloc記憶體之後不及時free掉記憶體,那麼很有可能會造成記憶體洩露的。那麼在c 上面,是不是也存在這樣的問題呢?結果是c 上面同樣也存在記憶體洩露的危險。這個危險就是如果new後面不能delete的話,也會造成記憶體的洩露。還有不清楚的朋友可以看看下面...