青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

大龍的博客

常用鏈接

統(tǒng)計(jì)

最新評論

多態(tài)性----vptr----vtable

多態(tài)性 (polymorphism) 是面向?qū)ο缶幊痰幕咎卣髦弧6?C++ 中,多態(tài)性通過虛函數(shù) (virtual function) 來實(shí)現(xiàn)。我們來看一段簡單的代碼:
  #include <iostream>
  using namespace std;
  class Base
  {
  int a;
  public:
  virtual void fun1() {cout<<"Base::fun1()"<<endl;}
  virtual void fun2() {cout<<"Base::fun2()"<<endl;}
  virtual void fun3() {cout<<"Base::fun3()"<<endl;}
  };
  class A:public Base
  {
  int a;
  public:
  void fun1() {cout<<"A::fun1()"<<endl;}
  void fun2() {cout<<"A::fun2()"<<endl;}
  };
  void foo (Base& obj)
  {
  obj.fun1();
  obj.fun2();
  obj.fun3();
  }
  int main()
  {
  Base b;
  A a;
  foo(b);
  foo(a);
  }
  運(yùn)行結(jié)果為:
  Base::fun1()
  Base::fun2()
  Base::fun3()
  A::fun1()
  A::fun2()
  Base::fun3()
  僅通過基類的接口,程序調(diào)用了正確的函數(shù),它就好像知道我們輸入的對象的類型一樣!
  那么,編譯器是如何知道正確代碼的位置的呢?其實(shí),編譯器在編譯時(shí)并不知道要調(diào)用的函數(shù)體的正確位置,但它插入了一段能找到正確的函數(shù)體的代碼。這稱之為 晚捆綁 (late binding) 或 運(yùn)行時(shí)捆綁 (runtime binding) 技術(shù)。
  通過virtual 關(guān)鍵字創(chuàng)建虛函數(shù)能引發(fā)晚捆綁,編譯器在幕后完成了實(shí)現(xiàn)晚捆綁的必要機(jī)制。它對每個(gè)包含虛函數(shù)的類創(chuàng)建一個(gè)表(稱為VTABLE),用于放置虛函數(shù)的地址。在每個(gè)包含虛函數(shù)的類中,編譯器秘密地放置了一個(gè)稱之為vpointer(縮寫為VPTR)的指針,指向這個(gè)對象的VTABLE。所以無論這個(gè)對象包含一個(gè)或是多少虛函數(shù),編譯器都只放置一個(gè)VPTR即可。VPTR由編譯器在構(gòu)造函數(shù)中秘密地插入的代碼來完成初始化,指向相應(yīng)的VTABLE,這樣對象就“知道”自己是什么類型了。 VPTR都在對象的相同位置,常常是對象的開頭。這樣,編譯器可以容易地找到對象的VTABLE并獲取函數(shù)體的地址。
  如果我們用sizeof查看前面Base類的長度,我們就會(huì)發(fā)現(xiàn),它的長度不僅僅是一個(gè)int的長度,而是增加了剛好是一個(gè)void指針的長度(在我的機(jī)器里面,一個(gè)int占4個(gè)字節(jié),一個(gè)void指針占4個(gè)字節(jié),這樣正好類Base的長度為8個(gè)字節(jié))。
  每當(dāng)創(chuàng)建一個(gè)包含虛函數(shù)的類或從包含虛函數(shù)的類派生一個(gè)類時(shí),編譯器就為這個(gè)類創(chuàng)建一個(gè)唯一的VTABLE。在VTABLE中,放置了這個(gè)類中或是它的基類中所有虛函數(shù)的地址,這些虛函數(shù)的順序都是一樣的,所以通過偏移量可以容易地找到所需的函數(shù)體的地址。假如在派生類中沒有對在基類中的某個(gè)虛函數(shù)進(jìn)行重寫(overriding),那末還使用基類的這個(gè)虛函數(shù)的地址(正如上面的程序結(jié)果所示)。
  

  至今為止,一切順利。下面,我們的試驗(yàn)開始了。
  就目前得知的,我們可以試探著通過自己的代碼來調(diào)用虛函數(shù),也就是說我們要找尋一下編譯器秘密地插入的那段能找到正確函數(shù)體的代碼的足跡。
  如果我們有一個(gè)Base指針作為接口,它一定指向一個(gè)Base或由Base派生的對象,或者是A,或者是其它什么。這無關(guān)緊要,因?yàn)閂PTR的位置都一樣,一般都在對象的開頭。如果是這樣的話,那么包含有虛函數(shù)的對象的指針,例如Base指針,指向的位置恰恰是另一個(gè)指針——VPTR。VPTR指向的 VTABLE其實(shí)就是一個(gè)函數(shù)指針的數(shù)組,現(xiàn)在,VPTR正指向它的第一個(gè)元素,那是一個(gè)函數(shù)指針。如果VPTR向后偏移一個(gè)Void指針長度的話,那么它應(yīng)該指向了VTABLE中的第二個(gè)函數(shù)指針了。
  這看來就像是一個(gè)指針連成的鏈,我們得從當(dāng)前指針獲取它指向的下一個(gè)指針,這樣我們才能“順藤摸瓜”。那么,我來介紹一個(gè)函數(shù):
  void *getp (void* p)
  {
  return (void*)*(unsigned long*)p;
  }
  我們不考慮它漂亮與否,我們只是試驗(yàn)。getp() 可以從當(dāng)前指針獲取它指向的下一個(gè)指針。如果我們能找到函數(shù)體的地址,用什么來存儲(chǔ)它呢?我想應(yīng)該用一個(gè)函數(shù)指針:
  typedef void (*fun)();
  它與Base中的三個(gè)虛函數(shù)相似,為了簡單我們不要任何輸入和返回,我們只要知道它實(shí)際上被執(zhí)行了即可。
  然后,我們負(fù)責(zé)“摸瓜”的函數(shù)登場了:
  fun getfun (Base* obj, unsigned long off)
  {
  void *vptr = getp(obj);
  unsigned char *p = (unsigned char *)vptr;
  p += sizeof(void*) * off;
  return (fun)getp(p);
  }
  第一個(gè)參數(shù)是Base指針,我們可以輸入Base或是Base派生對象的指針。第二個(gè)參數(shù)是VTABLE偏移量,偏移量如果是0那么對應(yīng)fun1(),如果是1對應(yīng)fun2()。getfun() 返回的是fun類型函數(shù)指針,我們上面定義的那個(gè)。可以看到,函數(shù)首先就對Base指針調(diào)用了一次getp(),這樣得到了vptr這個(gè)指針,然后用一個(gè) unsigned char指針運(yùn)算偏移量,得到的結(jié)果再次輸入getp(),這次得到的就應(yīng)該是正確的函數(shù)體的位置了。
  那么它到底能不能正確工作呢?我們修改main() 來測試一下:
  int main()
  {
  Base *p = new A;
  fun f = getfun(p, 0);
  (*f)();
  f = getfun(p, 1);
  (*f)();
  f = getfun(p, 2);
  (*f)();
  delete p;
  }
  激動(dòng)人心的時(shí)刻到來了,讓我們運(yùn)行它!
  運(yùn)行結(jié)果為:
  A::fun1()
  A::fun2()
  Base::fun3()
  至此,我們真的成功了。通過我們的方法,我們獲取了對象的VPTR,在它的體外執(zhí)行了它的虛函數(shù)。

posted on 2007-01-25 20:44 大龍 閱讀(4600) 評論(3)  編輯 收藏 引用

評論

# re: 多態(tài)性----vptr----vtable 2008-05-08 10:33 nitrotoluene

兄弟,受教了!  回復(fù)  更多評論   

# re: 多態(tài)性----vptr----vtable 2008-11-29 20:49 langzilingqi

了解了VPTR,反而又更深入地了解了虛函數(shù)的實(shí)現(xiàn)了,多謝!  回復(fù)  更多評論   

# re: 多態(tài)性----vptr----vtable 2015-05-05 20:41 mudongliang

非常好,學(xué)習(xí)了!  回復(fù)  更多評論   


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产精品腿扒开做爽爽爽挤奶网站| 久久国产手机看片| 欧美成人有码| 欧美电影免费观看| 麻豆精品精品国产自在97香蕉| 欧美一区二区三区四区高清| 午夜精品久久久久久久99水蜜桃| 亚洲视频高清| 亚洲免费视频网站| 欧美亚洲一区二区三区| 久久人人爽人人爽| 欧美精品成人| 国产精品色婷婷| 国产日韩欧美夫妻视频在线观看| 黑人巨大精品欧美黑白配亚洲 | 久久久亚洲国产美女国产盗摄| 欧美中文字幕视频| 久久国产成人| 欧美激情1区2区| 在线一区亚洲| 久久久欧美精品| 欧美日产国产成人免费图片| 国产精品久久久久久久9999| 在线观看久久av| 亚洲视频第一页| 老司机免费视频久久| 欧美成人精品福利| 亚洲免费在线播放| 欧美母乳在线| 亚洲高清视频在线观看| 午夜视频一区| 亚洲精品在线电影| 久久九九99| 亚洲精品国产系列| 国产精品一区一区三区| 国产伦精品一区二区三区视频黑人| 狠狠久久亚洲欧美| 一区二区三区国产| 巨胸喷奶水www久久久免费动漫| 日韩视频在线播放| 另类欧美日韩国产在线| 国产欧美一级| 亚洲自拍电影| 日韩午夜在线播放| 麻豆精品视频在线观看| 国内一区二区在线视频观看| 午夜精品国产| 日韩系列欧美系列| 久久久一本精品99久久精品66| 国产精品国产三级国产a| 狠狠综合久久| 久久精品中文| 欧美与欧洲交xxxx免费观看| 国产精品视频99| 亚洲免费网址| 亚洲一区二区三区精品视频| 欧美日韩四区| 一区二区高清| 亚洲精品1234| 麻豆精品视频| 日韩视频在线播放| 亚洲第一精品夜夜躁人人爽| 久久视频精品在线| 激情综合在线| 欧美14一18处毛片| 免费短视频成人日韩| 亚洲高清久久网| 欧美激情一区二区三区蜜桃视频 | 亚洲精品久久久久久久久| 免费在线日韩av| 亚洲美女免费视频| 日韩视频国产视频| 国产精品自拍一区| 久久久青草婷婷精品综合日韩| 欧美一区二视频| 一区二区视频欧美| 欧美激情区在线播放| 欧美精品入口| 午夜久久电影网| 欧美一区三区三区高中清蜜桃| 韩国精品久久久999| 久久综合狠狠综合久久综合88 | 久久精品国产69国产精品亚洲| 狠狠久久亚洲欧美专区| 欧美激情亚洲视频| 欧美视频在线观看| 久久精品国产一区二区三| 久久久99免费视频| 一本色道综合亚洲| 亚洲欧美影院| 亚洲精品午夜| 另类天堂视频在线观看| 欧美高清在线播放| 欧美性猛片xxxx免费看久爱 | 亚洲无线视频| 狠狠爱成人网| 日韩午夜在线| 在线观看91精品国产麻豆| 亚洲经典视频在线观看| 国产精品久久久免费| 免费久久99精品国产自在现线| 欧美另类人妖| 久久一区二区精品| 欧美日韩日本网| 欧美凹凸一区二区三区视频| 国产精品久久久久久久久免费樱桃| 久久久久九九视频| 欧美天天视频| 亚洲娇小video精品| 黄色一区二区在线| 亚洲一区久久久| 日韩一区二区久久| 久久精品国产v日韩v亚洲| 亚洲一区一卡| 欧美经典一区二区三区| 久久久精品免费视频| 国产精品v欧美精品v日韩 | 午夜国产精品视频免费体验区| 亚洲黄色免费网站| 欧美在线不卡视频| 香蕉精品999视频一区二区| 欧美日韩高清在线播放| 欧美国产精品va在线观看| 国产原创一区二区| 亚洲欧美另类在线观看| 亚洲视频一二| 欧美女同视频| 亚洲欧洲日产国产网站| 永久免费毛片在线播放不卡| 欧美一区二区精品久久911| 亚洲在线成人| 国产精品vvv| 在线性视频日韩欧美| 夜夜嗨av一区二区三区四区| 女人色偷偷aa久久天堂| 美女爽到呻吟久久久久| 在线观看成人网| 久久人体大胆视频| 欧美ed2k| 亚洲黄色免费电影| 欧美国产日韩二区| 亚洲人永久免费| 亚洲午夜免费视频| 国产精品成人v| 亚洲性线免费观看视频成熟| 亚洲一区制服诱惑| 国产精品入口麻豆原神| 欧美一区二视频| 美女尤物久久精品| 亚洲黄色精品| 欧美日韩一区二区三区在线看 | 亚洲精品国产精品国产自| 亚洲国产成人av| 欧美国产在线电影| 日韩视频在线观看免费| 中文有码久久| 国产日韩精品视频一区二区三区| 欧美一区二区播放| 欧美激情欧美激情在线五月| 日韩一级不卡| 国产精品一二三| 久久综合九色| 亚洲精品一区二区三区不| 亚洲免费一在线| 国外视频精品毛片| 欧美精品导航| 欧美一二三视频| 欧美风情在线观看| 亚洲一区精品视频| 国产综合欧美在线看| 久久综合国产精品| 亚洲视频图片小说| 久久这里有精品15一区二区三区| 最新中文字幕一区二区三区| 国产精品第一页第二页第三页| 久久本道综合色狠狠五月| 亚洲精美视频| 久久免费视频观看| 亚洲午夜女主播在线直播| 精品1区2区| 国产精品h在线观看| 久久先锋资源| 亚洲一区在线播放| 亚洲国产99| 久久久久综合网| 亚洲综合成人婷婷小说| 亚洲国产成人午夜在线一区| 国产精品久久久久aaaa樱花| 久久在线精品| 午夜精品一区二区三区四区| 亚洲国产一区二区在线| 久久婷婷av| 午夜伦理片一区| 一区二区三区四区五区视频| 在线精品视频一区二区三四| 国产精品视频精品视频| 欧美日本一道本在线视频| 久久夜色撩人精品| 欧美一区二区免费观在线| 亚洲视频欧美视频|