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

大龍的博客

常用鏈接

統(tǒng)計

最新評論

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

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

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

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

評論

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

兄弟,受教了!  回復  更多評論   

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

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

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

非常好,學習了!  回復  更多評論   


只有注冊用戶登錄后才能發(fā)表評論。
網(wǎng)站導航: 博客園   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>
            久久久91精品国产| 一本一道久久综合狠狠老精东影业| 亚洲欧美日韩天堂一区二区| 欧美午夜免费影院| 亚洲影院免费观看| 亚洲欧美第一页| 国产亚洲午夜| 欧美高清免费| 欧美日韩在线不卡一区| 亚洲欧美大片| 久久精品亚洲一区二区三区浴池 | 亚洲欧洲日本国产| 欧美精品久久久久久久| 亚洲免费视频网站| 久久国产精品黑丝| 日韩亚洲精品视频| 亚洲欧美视频一区二区三区| 国产午夜亚洲精品理论片色戒| 久久综合激情| 欧美日本二区| 久久久精品欧美丰满| 女女同性精品视频| 亚洲欧美日韩一区二区三区在线| 欧美一区二区三区日韩视频| 亚洲国产高清一区| 亚洲香蕉伊综合在人在线视看| 国产午夜精品在线观看| 亚洲国产成人av在线| 国产精品久久久久aaaa九色| 久久一区免费| 国产精品久久999| 欧美大片在线观看一区| 国产精品v欧美精品∨日韩| 老鸭窝毛片一区二区三区| 欧美高清视频一区二区| 久久福利一区| 欧美午夜一区二区福利视频| 免费成人黄色| 亚洲欧美在线另类| 国内精品亚洲| 久久久久久成人| 欧美亚洲一区| 亚洲你懂的在线视频| 国产精品v欧美精品v日本精品动漫 | 欧美激情91| 欧美在线影院| 欧美无砖砖区免费| 欧美激情综合色| 一色屋精品视频在线看| 亚洲专区在线| 亚洲影院色在线观看免费| 欧美成人一区二区三区在线观看| 中文欧美在线视频| 欧美成人午夜| 亚洲精品精选| 亚洲视频香蕉人妖| 亚洲精品五月天| 久久香蕉国产线看观看网| 欧美一区二区三区免费大片| 欧美日韩裸体免费视频| 亚洲国产天堂久久综合| 在线不卡亚洲| 久久久久久久久久久一区| 欧美一级专区免费大片| 国产精品黄视频| 亚洲无吗在线| 性久久久久久久久久久久| 国产精品久久久久影院色老大 | 亚洲欧美一区二区视频| 欧美日韩精品久久| 亚洲精品日产精品乱码不卡| 亚洲精品视频一区| 欧美精品性视频| 日韩视频亚洲视频| 亚洲社区在线观看| 国产精品久久久久一区| 亚洲性xxxx| 久久爱另类一区二区小说| 国产日韩欧美高清| 欧美中文在线观看国产| 久久一区二区三区四区| 永久免费毛片在线播放不卡| 久久综合亚州| 亚洲精品九九| 性色av一区二区三区| 国产亚洲欧美一区| 玖玖玖国产精品| 亚洲激情视频在线播放| 亚洲视频一区| 国产视频精品xxxx| 久久一二三国产| 最新国产の精品合集bt伙计| 亚洲视频一区| 国语精品中文字幕| 老司机午夜精品视频在线观看| 亚洲人体大胆视频| 亚洲欧美三级在线| 在线观看视频免费一区二区三区| 欧美大片一区| 亚洲网站视频| 欧美国产日韩亚洲一区| 亚洲天堂免费观看| 韩国一区二区三区美女美女秀| 久热精品在线| 亚洲一区中文| 欧美电影在线免费观看网站| 亚洲午夜国产成人av电影男同| 国产欧美在线播放| 欧美韩日一区| 欧美诱惑福利视频| 99精品热视频| 欧美成人免费播放| 欧美一区二区三区视频免费播放 | 亚洲国产日韩美| 国产精品xxxxx| 麻豆亚洲精品| 午夜一区二区三区不卡视频| 亚洲第一中文字幕在线观看| 欧美一区二区日韩| 一区二区三区精品国产| 在线日本成人| 国产一区成人| 欧美亚州在线观看| 欧美—级高清免费播放| 久久久久.com| 欧美一区二区视频在线观看| 亚洲免费播放| 亚洲福利精品| 男人的天堂亚洲| 久久视频在线视频| 久久国产欧美精品| 亚洲欧美欧美一区二区三区| 亚洲美女精品一区| 亚洲国产精品电影| 伊人成年综合电影网| 国产深夜精品| 国产欧美91| 国产精品色午夜在线观看| 欧美日韩综合在线| 欧美理论在线| 欧美日韩免费观看一区=区三区| 久久久免费av| 久久人人超碰| 久久综合国产精品| 久久久噜噜噜久噜久久| 久久久久久日产精品| 久久精品国产久精国产思思| 欧美一区免费| 久久久久久久一区| 男人的天堂成人在线| 欧美成人性生活| 欧美精品首页| 欧美午夜视频网站| 国产精品日日摸夜夜摸av| 国产精品视频久久久| 亚洲精品乱码久久久久久黑人| 亚洲国产精品www| 欧美激情一区二区三区四区| 免费精品99久久国产综合精品| 99热免费精品| 亚洲午夜在线观看| 亚洲自拍偷拍福利| 欧美在线一区二区三区| 久久免费偷拍视频| 亚洲二区在线视频| 亚洲伦伦在线| 香港久久久电影| 久久蜜臀精品av| 欧美日韩不卡| 国产伦精品一区二区三区视频黑人| 国产欧美一区二区精品婷婷| 一色屋精品视频在线看| 亚洲最新在线视频| 久久国产精品久久久| 男人的天堂成人在线| 亚洲理论在线观看| 欧美在线一级视频| 欧美绝品在线观看成人午夜影视| 国产精品入口福利| 亚洲国产高清自拍| 亚洲欧美欧美一区二区三区| 亚洲国产三级| 久久久免费观看视频| 亚洲欧洲精品一区二区三区波多野1战4| 99精品国产在热久久| 久久精品视频播放| 欧美午夜影院| 亚洲第一精品福利| 亚洲欧美视频在线观看视频| 美女久久一区| 亚洲综合二区| 欧美日韩国产探花| 亚洲第一天堂av| 午夜精品久久久久久久99热浪潮 | 亚洲一区日韩| 欧美大片在线观看一区| 亚洲欧美日韩精品久久亚洲区 | 国产精品mv在线观看| 在线免费观看日本欧美| 亚洲女人天堂av|