- #include <iostream>
- using namespace std;
- class base
- {
- public:
- base(){cout << "base::base() called" << endl;}
- void f(){cout << "base::f() called" << endl;}
- virtual void g() {cout << "virtual base::g() called" << endl;}
- virtual void h() {cout << "virtual base::h() called" << endl;}
- static void k() {cout << " static base::k() called" << endl;}
- private:
- static int i;
- int j;
- };
- int main()
- {
- cout << sizeof(base) << endl;
- typedef void (*PFUN)(void);
- PFUN pfun;
- base t;
- cout << "虚函数表的地址: " << (int*)(*(int*)(&t)) << endl;
- cout << "虚函数表第一个函数的地址: " << (int*)*(int*)(&t) << endl;
- pfun = (PFUN)*((int*)*(int*)(&t));
- pfun();
- pfun = (PFUN)*((int*)*(int*)(&t) + 1);
- pfun();
- return 0;
- }
在程序中我们定义了一个类对象: base t;
(int *)(&t) 表示类对象的地址。其实也是vptr的地址。这个通过我们的程序也可以证明出来.
(int *)(*(int*)(&t)) 这个就可以认为是虚函数表的地址了。因为(int *)(&t) 是vptr的地址,我们对其进行解引用就是虚函数表的地址了。然后我们通过(int*)转换一下就可以输出了。
现在知道虚函数表的地址了,那我们对其进行解引用,那自然就可以得到虚函数表中的第一个函数的地址了。即:
(int*)(*(int *)(*(int*)(&t)) 这个就是虚函数表的第一个虚函数的地址了。
程序中我们这样测试
typedef void (*PFUN)(void); 这句话我们定义了一个函数指针类型PFUN
PFUN pfun;定义一个函数指针变量:
pfun = (PFUN)(*(int *)(*(int*)(&t)) ;
pfun(); //调用的便是虚函数表中第一个虚函数了。那如何调用第二个呢。因为虚函数表是顺序存储的,自然+1就可以得到了。
pfun = (PFUN)*((int *)(*(int*)(&t) + 1); //此刻自然调用的是第二个虚函数了。其他函数依次类推。
- #include <iostream>
- using namespace std;
- class base
- {
- public:
- base(int x = 0):a(x){}
- virtual void f(){cout << "base::f()" << endl;}
- virtual void g(){cout << "base::g()" << endl;}
- private:
- int a;
- };
- int main()
- {
- typedef void (*PFUN)();
- PFUN pfun;
- //验证整个对象的内存模型,
- base t(3);
- cout << "对象的地址 " << (int*)(&t) << endl; //对象的地址
- cout << "base::a= " << *((int*)(&t)+1) << endl;
- //验证虚函数表的模型
- cout << "虚函数表的地址 " << (int*)(*(int*)(&t)) << endl;
- cout << "第一个虚函数的地址 " << *((int*)(*(int*)(&t))) << endl;
- cout << "第二个虚函数的地址 " << *((int*)(*(int*)(&t))+1) << endl;
- pfun = (PFUN)*((int*)(*(int*)(&t)));
- cout << "vptr[0] ";
- pfun();
- cout << "vptr[1] ";
- pfun = (PFUN)*((int*)(*(int*)(&t))+1);
- pfun();
- return 0;
- }
验证结果: