概述
含有虛函數的類,其實例化的對象都包括一個虛函數表指針vptr(virtual table pointer,虛函數表指針),該指針就在對象的開始,也就是說對象的地址就是虛函數指針的地址。
而虛函數指針指向了虛函數表。虛函數表實際上就是所有虛函數的地址數組,4B表示一個虛函數地址(入口)。
構造過程
引用:https://www.cnblogs.com/malecrab/p/5572730.html
驗證代碼
驗證環境爲Win7 64位操作系統 + VS2010 旗艦版
#include <iostream> using namespace std; class Parent{ public: long b; virtual void foo() {cout << "Parent foo" << endl;}; virtual void bar() {cout << "Parent bar" << endl;}; }; class Son : public Parent{ public: long d; virtual void bar() {cout << "Son bar" << endl;}; virtual void quz() {cout << "Son quz" << endl;}; }; typedef void(*pFunc)(void); int main() { Parent p; Son s; p.b = 100; s.b = 200; s.d = 300; pFunc pFun = NULL; cout << "父類虛函數表指針地址 0x" << (int*)(&p) << endl; cout << "父類虛函數表地址: 0x" << (int*)*(int*)(&p) << endl; cout << "父類第一個虛函數地址:0x" << (int*)*(int*)*(int*)(&p)<< endl; cout << "父類第二個虛函數地址:0x" << (int*)*(int*)(*(int*)(&p) + 4)<< endl; cout << "子類虛函數表指針地址 0x" << (int*)(&s) << endl; cout << "子類虛函數表地址: 0x" << (int*)*(int*)(&s) << endl; cout << "子類第一個虛函數地址:0x" << (int*)*(int*)*(int*)(&s)<< endl; cout << "子類第二個虛函數地址:0x" << (int*)*(int*)(*(int*)(&s) + 4)<< endl; cout << "子類第三個虛函數地址:0x" << (int*)*(int*)(*(int*)(&s) + 8)<< endl; //父類第一個虛函數指針 pFun = (pFunc)*(int*)*(int*)(&p); pFun(); //父類第二個虛函數指針 pFun = (pFunc)*(int*)(*(int*)(&p) + 4); pFun(); //子類第一個虛函數指針 pFun = (pFunc)*(int*)*(int*)(&s); pFun(); //子類第二個虛函數指針 pFun = (pFunc)*(int*)(*(int*)(&s) + 4); pFun(); //子類第三個虛函數指針 pFun = (pFunc)*(int*)(*(int*)(&s) + 8); pFun(); return 0; }
動態調試
在內存中檢視父類的地址&p,輸入'&p'後自動轉換爲0x39FD04。可以看到該地址的4B爲0xb47938,就是虛函數表指針的值。
我們看這個地址,指向的區域就是虛函數表了。可以看到分別是0xb411f4,0xb41032.
子類是一樣的,就不贅述了。
下面看下父類和子類的對象,VS中的值。可以看到vfptr的構成。但是子類對象s實際應該有三個虛函數,但是這裏並沒有體現出來第三個。