程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> 多態實現之虛函數,多態實現之函數

多態實現之虛函數,多態實現之函數

編輯:C++入門知識

多態實現之虛函數,多態實現之函數


多態的實現分為靜態多態和動態多態,靜態多態主要靠函數重載,動態多態主要靠虛函數

當類中聲明了虛函數之後,該類的內存映像會獲得一個虛表指針,叫做_vfptr指向該類的虛表,下面的我測試使用的類圖(有的沒必要的東西沒有寫)

這裡恰好還是一個菱形繼承,但是就像我之前說的虛繼承和虛表關系不大,所以單繼承也是可以測試的

其中高亮的部分就是虛表指針,用內存窗口就可以看到虛表中存放的東西了,每一個多態類的對象都有一個自己的虛表指針,並且多繼承的對象會有多個_vptr指針

m和m1的_vptr指向同一個虛表

多繼承對象有更多的_vfptr指向不同的虛表

 

這裡我們雖然看到的是_vfptr是放在m對象的最後,但是在內存中_vfptr是存放在m內存空間一開頭的地方!!如果我們想要強取虛表並且把虛表中的函數指針打印出來看看的話,只要取m的地址(就是一開始的頭地址)就可以了,=(雖然一般人不會這麼做,如果只是想看看的話),如果還想打印其他的虛表的話就把指針偏移一下,_vfptr就是指向虛表的指針,就相當於指向一個函數指針數組的第一個元素指針,獲得了這個指針之後就可以像訪問數組一樣訪問這個虛表了

如下圖所示對象m地址空間一開始就是虛表指針_vfptr,緊接著是虛繼承表指針_vbptr(要區分開!)(虛繼承表詳解看菱形繼承那篇博客)

強取虛表打印代碼

 1 void PrintVtable(int *vTable)
 2 {
 3     for (int i = 0; vTable[i] != 0; i++)
 4     {
 5         printf("%x\n", vTable[i]);
 6         FUNC f = (FUNC)vTable[i];
 7         f();
 8     }
 9 }//因為指針和int型變量都是4個字節,所以我們用整型變量來存放地址
10 
11 
12 
13 
14 int *vTable = (int *)(*(int *)&m);
15 PrintVtable(vTable);

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved