Author: bakari Date: 2012.4.8
虛函數是C++中非常重要的一個概念,它最大的好處是能夠觸發動态綁定。C++中的函數預設不使用動态綁定,要觸發動态綁定,必須滿足 兩個條件:
第一,隻有指定為虛函數的成員函數才能進行動态綁定,成員函數預設為非虛函數,非虛函數不進行動态綁定;
第二,必須通過基類類型的指針或引用進行函數的調用。具體了解指針或引用在使用繼承層次中某一類型的對象時會發生什麼,本文不展開讨論,
這兩天主要研習了虛函數的具體應用這一塊,而它的應用又非常廣泛,學MFC的應該能夠感受到它的強大,要說是總結也不一定能夠總結全,本人目前也處在studying中,是以用10個具體的例子來說明。例子是從難 到易,看到的朋友如果懂前面的可以不用看後面的。每一個例子就是一個類,通過類在記憶體中的布局來形象地分析虛函數究竟是如何運作的。圖表示可能抽象一點,一般帶有V開頭的表示一個虛函數表,如果是學過編譯原理這門課就很容易看懂,沒學過的隻要懂虛函數的一些機制,耐着性子也是沒問題的。每個圖示都配有相應的代碼。可以對照着代碼來看。
1、 虛函數繼承的複雜例子
2、 菱形繼承無虛拟繼承的情況
3、 虛拟繼承的簡單情況
4、 單一普通繼承(無虛函數)
5、 單一繼承(含虛函數)(虛函數表隻有一個)
6、 多重繼承(不含虛函數)
7、 多重繼承(一個含虛函數,一個不含虛函數)
8、 多重繼承(兩個都含有虛函數)
9、 純虛汗繼承
10、 private 的虛函數
1、虛函數繼承的複雜例子,見下圖:
見圖:左邊是這個類的記憶體布局,右邊是繼承圖示。 farther類和Uncle類都是虛拟繼承,其内部也都有偏移表,但我覺得這兩個表隻是内部隐藏的,不在Son的記憶體布局中表示出來,本題Son的記憶體隻有32個位元組,如果表示出來就不止32個了,但是下面這個地方在記憶體中顯示是00 00 00 00,我猜想是不是GrandFather的偏移位址。
VbtSon(Father)
Farther~Num
VbtSon(Uncle)
Uncle~Num
Son~Num
Offset(這個地方??)
Vftable(GrandFather)
GrandFather~Num
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuUTMkJTY5Y2YkZzMllTZ2gTOkVDO0IjMxIzMhJDZzATMfdWbp9CXt92Yu4GZjlGbh5SZslmZxl3Lc9CX6MHc0RHaiojIsJye.png)
例子代碼:
運作情況:
2、 菱形繼承無虛拟繼承的情況
VPTr1(Father)
GrandFarther~Num
Father~Num
VPtr(Uncle)
3、 虛拟繼承的簡單情況 見下圖:
VPTrD(A) 4
Offset(A) 4
A~number 4
D~number 4
VPtr(Base) 4
Base~Number
12 + 3cc + 4 = 40
4、單一普通繼承(無虛函數)(這個沒什麼好說的)
記憶體布局
Father~Number
Son~Number
5、單一繼承(含虛函數)(虛函數表隻有一個)見圖:
VPTr(father)
Father~number
Son~number
Child~number
6、多重繼承(不含虛函數)(這個也沒什麼好說的)
直接看代碼:
7、多重繼承(一個含虛函數,一個不含虛函數)(類似單一繼承)
8、多重繼承(兩個都含有虛函數)
VPTr(Son)
Son~number Child~number
20個位元組
9、純虛汗繼承
(隻在父類中申明,并在子類中實作申明的函數才可以用)
記憶體配置設定與前面隻含虛函數的情況類似
10、private 的虛函數
OK,做這個東西很辛苦,沒辦法,搞技術的就得這樣。
寫這些程式然後進行測試是很輕松的一件事,然而要把這些東西以文字的方式整理出來,的确不是一件容易的事。是以,就有很多IT高手,技術流,Coding很厲害,但對于文字的東西就不是很感冒,不過沒關系,每個人有每個人的不同的需求,我是喜歡沒事總喜歡寫寫的人,我想寫的越多思路就不會堵塞
祝願每一個朋友學習愉快,技術成精!