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

大龍的博客

常用鏈接

統計

最新評論

多態性----vptr----vtable

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

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

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

評論

# re: 多態性----vptr----vtable 2008-05-08 10:33 nitrotoluene

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

# re: 多態性----vptr----vtable 2008-11-29 20:49 langzilingqi

了解了VPTR,反而又更深入地了解了虛函數的實現了,多謝!  回復  更多評論   

# re: 多態性----vptr----vtable 2015-05-05 20:41 mudongliang

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


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   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>
            欧美日韩一区二区三区在线| 欧美在线观看日本一区| 欧美日韩视频在线一区二区 | 欧美精品一区二区高清在线观看| 午夜久久美女| 欧美一区二区三区免费观看| 欧美亚洲自偷自偷| 久久天堂国产精品| 欧美日本免费| 欧美亚洲不卡| 国产亚洲精品一区二555| 狠狠干综合网| 亚洲精品在线电影| 国产麻豆视频精品| 激情欧美一区二区三区| 亚洲裸体视频| 欧美一级大片在线观看| 欧美 日韩 国产一区二区在线视频| 久久av一区二区三区亚洲| 女同一区二区| 亚洲欧美精品在线观看| 欧美69视频| 国产一区二区三区成人欧美日韩在线观看 | 亚洲另类黄色| 先锋影音国产精品| 亚洲第一页自拍| 亚洲国产综合在线看不卡| 亚洲综合国产激情另类一区| 免费看亚洲片| 国产一区二区三区不卡在线观看| 91久久精品一区二区别| 亚洲欧美在线网| 欧美成人一区在线| 亚洲精品国产精品乱码不99按摩| 亚洲激情欧美| 久久精品五月婷婷| 国产精品久久久久9999吃药| 亚洲开发第一视频在线播放| 国产一区二区在线观看免费| 亚洲精品乱码久久久久久蜜桃麻豆| 亚洲激情网站| 久久久久欧美| 亚洲天堂网在线观看| 欧美精品一区二| 91久久夜色精品国产九色| 欧美影片第一页| 亚洲调教视频在线观看| 欧美另类极品videosbest最新版本| 国产女人18毛片水18精品| 99精品国产在热久久婷婷| 欧美高清你懂得| 久久嫩草精品久久久精品一| 国产精品一区二区在线| 亚洲视频一区| 亚洲美女淫视频| 欧美日本在线观看| 中国日韩欧美久久久久久久久| 老鸭窝亚洲一区二区三区| 欧美在线综合| 国内一区二区在线视频观看| 久久久久久高潮国产精品视| 欧美日韩国产区一| 欧美一区=区| 国产一区二区丝袜高跟鞋图片| 99综合视频| 日韩视频免费看| 欧美性jizz18性欧美| 亚洲影院一区| 亚洲自拍偷拍福利| 国产一区二区三区高清 | 狠狠久久亚洲欧美专区| 久久久一区二区| 久久米奇亚洲| 日韩视频在线永久播放| 亚洲美女色禁图| 国产精品一区=区| 另类av导航| 欧美日本视频在线| 久久激情五月激情| 美女日韩欧美| 亚洲欧美视频| 久久综合国产精品台湾中文娱乐网| 激情久久五月天| 亚洲日本va在线观看| 国产精品福利av| 久久久蜜桃一区二区人| 开心色5月久久精品| 一区二区三区日韩| 久久激情网站| 亚洲先锋成人| 久久久久久噜噜噜久久久精品| 一本色道久久精品| 久久成人精品电影| 欧美国产日本在线| 国产婷婷色一区二区三区| 久久久久久午夜| 欧美日韩国产高清视频| 久久久精品2019中文字幕神马| 久久综合久久久久88| 亚洲主播在线| 欧美福利电影网| 久久中文字幕一区| 国产欧美一区二区三区久久| 亚洲激情av在线| ●精品国产综合乱码久久久久| 你懂的国产精品| 国产精品久久久久影院色老大 | 欧美日本簧片| 老司机精品久久| 国产精品欧美久久| 欧美激情在线免费观看| 国产精品日韩在线| 亚洲人成网站777色婷婷| 狠狠色丁香久久婷婷综合丁香| 91久久线看在观草草青青| 国产在线国偷精品产拍免费yy| 亚洲国产精彩中文乱码av在线播放| 欧美日韩你懂的| 欧美日韩中文字幕精品| 欧美日韩精品综合| 亚洲国产欧美国产综合一区| 韩国在线一区| 欧美在线播放视频| 久久精品国产69国产精品亚洲| 乱中年女人伦av一区二区| 久久久中精品2020中文| 国产午夜亚洲精品羞羞网站| 制服丝袜亚洲播放| 亚洲一区精品在线| 国产精品大片| 亚洲自拍偷拍色片视频| 欧美一区二区视频在线观看2020| 欧美日韩国产高清| 夜夜嗨网站十八久久| 亚洲愉拍自拍另类高清精品| 欧美日韩亚洲综合一区| 日韩视频亚洲视频| 亚洲一区三区电影在线观看| 欧美日韩综合精品| 亚洲一区二区三区在线看| 羞羞色国产精品| 狠狠久久综合婷婷不卡| 欧美va天堂| 亚洲伦伦在线| 先锋影音一区二区三区| 国内精品视频在线播放| 久久精品理论片| 免费亚洲一区二区| 99在线精品免费视频九九视| 欧美日韩精品一区二区天天拍小说| 亚洲区一区二| 亚洲制服少妇| 一区二区三区中文在线观看 | 久久伊人一区二区| 久久成人18免费网站| 久久精品国产v日韩v亚洲 | 国产精品亚发布| 久久成人免费网| 亚洲高清资源综合久久精品| av成人动漫| 国产视频不卡| 欧美大胆a视频| 亚洲综合电影一区二区三区| 麻豆精品视频在线观看| 日韩一区二区久久| 国产情人节一区| 玖玖在线精品| 亚洲香蕉网站| 欧美黄色一区| 亚洲欧美在线x视频| 一区二区三区无毛| 国产精品大片wwwwww| 久久精品国产亚洲aⅴ| 亚洲国产一区二区三区高清| 午夜精品免费| 99视频热这里只有精品免费| 国产精品久久毛片a| 久久亚洲午夜电影| 亚洲综合社区| 欧美激情精品久久久久久| 午夜在线观看免费一区| 99国产精品| 伊人伊人伊人久久| 国产精品视频大全| 欧美精品免费观看二区| 久久久亚洲欧洲日产国码αv| 亚洲欧洲日本专区| 久久久久www| 亚洲欧美日韩国产成人精品影院| 欧美日韩精品| 麻豆精品视频在线| 欧美一区二区三区四区高清 | 亚洲欧美日韩爽爽影院| 91久久久久久国产精品| 久久婷婷国产综合国色天香| 亚洲自拍偷拍色片视频| 亚洲人成人99网站| 黄色欧美日韩| 国精品一区二区| 国产精品一区二区三区久久|