**:
1、c++實現多型的方法
其實很多人都知道,虛函式在c++中的實現機制就是用虛表和虛指標,但是具體是怎樣的呢?從more effecive c++其中一篇文章裡面可以知道:是每個類用了乙個虛表,每個類的物件用了乙個虛指標。具體的用法如下:
class a
;class b : public a
;//a,b的實現省略
因為a有virtual void f(),和g(),所以編譯器為a類準備了乙個虛表vtablea,內容如下:
a::f 的位址
a::g 的位址
b因為繼承了a,所以編譯器也為b準備了乙個虛表vtableb,內容如下:
a::f 的位址
b::g 的位址
注意:因為b::g是重寫了的,所以b的虛表的g放的是b::g的入口位址,但是f是從上面的a繼承下來的,所以f的位址是a::f的入口位址。
然後某處有語句 b bb;的時候,編譯器分配空間時,除了a的int a,b的成員int b;以外,還分配了乙個虛指標vptr,指向b的虛表vtableb,bb的布局如下:
vptr : 指向b的虛表vtableb
int a: 繼承a的成員
int b: b成員
當如下語句的時候:
a *pa = &bb;
pa的結構就是a的布局(就是說用pa只能訪問的到bb物件的前兩項,訪問不到第三項int b)
那麼pa->g()中,編譯器知道的是,g是乙個宣告為virtual的成員函式,而且其入口位址放在**(無論是vtalbea表還是vtalbeb表)的第2項,那麼編譯器編譯這條語句的時候就如是轉換:call *(pa->vptr)[1](c語言的陣列索引從0開始哈~)。
這一項放的是b::g()的入口位址,則就實現了多型。(注意bb的vptr指向的是b的虛表vtableb)
另外要注意的是,如上的實現並不是唯一的,c++標準只要求用這種機制實現多型,至於虛指標vptr到底放在乙個物件布局的**,標準沒有要求,每個編譯器自己決定。我以上的結果是根據g++ 4.3.4經過反彙編分析出來的。
2、兩種多型實現機制及其優缺點
除了c++的這種多型的實現機制之外,還有另外一種實現機制,也是查表,不過是按名稱查表,是smalltalk等語言的實現機制。這兩種方法的優缺點如下:
(1)、按照絕對位置查表,這種方法由於編譯階段已經做好了索引和表項(如上面的call *(pa->vptr[1]) ),所以執行速度比較快;缺點是:當a的virtual成員比較多(比如1000個),而b重寫的成員比較少(比如2個),這種時候,b的vtableb的剩下的998個表項都是放a中的virtual成員函式的指標,如果這個派生體系比較大的時候,就浪費了很多的空間。
比如:gui庫,以mfc庫為例,mfc有很多類,都是乙個繼承體系;而且很多時候每個類只是1,2個成員函式需要在派生類重寫,如果用c++的虛函式機制,每個類有乙個虛表,每個表裡面有大量的重複,就會造成空間利用率不高。於是mfc的訊息對映機制不用虛函式,而用第二種方法來實現多型,那就是:
3、總結:
如果繼承體系的基類的virtual成員不多,而且在派生類要重寫的部分佔了其中的大多數時候,用c++的虛函式機制是比較好的;
但是如果繼承體系的基類的virtual成員很多,或者是繼承體系比較龐大的時候,而且派生類中需要重寫的部分比較少,那就用名稱查詢表,這樣效率會高一些,很多的gui庫都是這樣的,比如mfc,qt
ps. 其實,自從計算機出現之後,時間和空間就成了永恆的主題,因為兩者在98%的情況下都無法協調,此長彼消;這個就是電腦科學中的根本瓶頸之所在。軟體科學和演算法的發展,就看能不能突破這對時空權衡了。呵呵
何止電腦科學如此,整個宇宙又何嘗不是如此呢?最基本的宇宙之謎,還是時間和空間~
c++的虛函式使用了乙個虛函式表來存放了每乙個虛函式的入口位址,這個虛函式表又使用乙個虛函式指標來進行訪問。通常,虛函式指標都放在物件模型的第乙個位置存放,這樣訪問徐函式指標的速度最快,沒有偏移量。通過虛函式指標,找到虛函式表,進而再做乙個次偏移量計算,來得到真實虛函式的入口位址,從而訪問了虛函式。這樣看來,訪問乙個虛函式將使用兩次間接計算,故要失去一些時間效率。另外,使用了虛函式,那麼就要消耗一些空間,存放虛函式指標。但是,這都是值得的,為了實現多型。
C 多型實現之虛方法
控制台應用程式中,新建乙個people類檔案,如下 using system using system.collections.generic using system.linq using system.text namespace 13多型 public string name 1.第一,將父類...
C 基礎 虛方法實現多型
虛方法 用virtual修飾的方法叫做虛方法 虛方法可以在子類中通過override關鍵字來重寫 常見的虛方法 tostring equals 虛方法特點總結 1,在父類中把需要設定為虛方法的方法前加virtual標記 2,虛方法在父類中必須有實現,哪怕是空實現 3,子類繼承父類後,可以選擇對虛方法...
虛方法實現多型
大家都知道物件導向的三大特徵,封裝 繼承 多型,這裡解釋一下多型 同一操作作用於不同的物件,可以有不同的解釋,產生不同的執行結果,這就是多型性。換句話說,實際上就是同乙個型別的例項呼叫 相同 的方法,產生的結果是不同的。這裡的 相同 打上雙引號是因為這裡的相同的方法僅僅是看上去相同的方法,實際上它們...