int main() { B b; b.f=&B_Mem; //B_Mem代表B的“虛函數(shù)” D d; d.f=&D_Mem; //以D_Mem來(lái)覆蓋(override)B的虛函數(shù) call_virtual(&b); //輸出“I am B” call_virtual(&d); //輸出“I am D” } 在這個(gè)改進(jìn)的例子中,派生類對(duì)象可以通過(guò)修改函數(shù)指針f的指向,從而獲得特定的行為,這里重要的是,call_virtual函數(shù)不再需要通過(guò)丑陋的if-else語(yǔ)句來(lái)判定對(duì)象的具體類型,而只是簡(jiǎn)單的通過(guò)一個(gè)指針來(lái)調(diào)用“虛函數(shù)”——這時(shí)候,假如派生類需要改變具體的行為,則可以將相應(yīng)的函數(shù)指針指向它自己的函數(shù)即可,這招“偷梁換柱”通過(guò)增加一個(gè)間接層的辦法“神不知鬼不覺(jué)”地將“虛函數(shù)”替換(Override)掉了。 然而,這招仍然還有缺點(diǎn)——要用戶手動(dòng)實(shí)現(xiàn),可擴(kuò)展性差,透明性差等等。然而,它的思想已經(jīng)接近現(xiàn)代編譯器對(duì)多態(tài)機(jī)制的實(shí)現(xiàn)手法了。
現(xiàn)在,關(guān)于C++的多態(tài)機(jī)制基本已經(jīng)明了。剩下的就是多重繼續(xù)下的虛函數(shù)表格局,大同小異,就不多說(shuō)了。只不過(guò),其中還是有一些微妙的細(xì)節(jié)的,可以參見(jiàn)《Inside C++ Object Model》(Lippman著)(中文名《深入C++對(duì)象模型》——侯捷譯)。
public class C:IFirst,Isecond { public override void f1(){} public override void f2(){} public override void s1(){} public virtual void c1(){} } 類型C的內(nèi)存布局大體是這樣的(由于.NET是單根的繼續(xù)結(jié)構(gòu),每個(gè)類都隱式的繼續(xù)自O(shè)bject,所以,類型C的“虛函數(shù)表”中包含Object的所有成員函數(shù))