单个类的内存布局模型

Code:
  1. #include <iostream>   
  2. using namespace std;   
  3. class base   
  4. {   
  5. public:   
  6.     base(){cout << "base::base() called" << endl;}   
  7.     void f(){cout << "base::f() called" << endl;}   
  8.     virtual void g() {cout << "virtual base::g() called" << endl;}   
  9.     virtual void h() {cout << "virtual base::h() called" << endl;}   
  10.     static void k() {cout << " static base::k() called" << endl;}   
  11. private:   
  12.     static int i;   
  13.     int j;   
  14. };   
  15. int main()   
  16. {   
  17.     cout << sizeof(base) << endl;   
  18.     typedef  void (*PFUN)(void);   
  19.     PFUN pfun;   
  20.     base t;   
  21.     cout << "虚函数表的地址: " << (int*)(*(int*)(&t)) << endl;   
  22.     cout << "虚函数表第一个函数的地址: " << (int*)*(int*)(&t) << endl;   
  23.     pfun = (PFUN)*((int*)*(int*)(&t));   
  24.     pfun();   
  25.     pfun = (PFUN)*((int*)*(int*)(&t) + 1);   
  26.     pfun();   
  27.     return 0;   
  28. }  

在程序中我们定义了一个类对象: 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); //此刻自然调用的是第二个虚函数了。其他函数依次类推。

Code:
  1. #include <iostream>   
  2. using namespace std;   
  3. class base   
  4. {   
  5. public:   
  6.     base(int x = 0):a(x){}   
  7.     virtual void f(){cout << "base::f()" << endl;}   
  8.     virtual void g(){cout << "base::g()" << endl;}   
  9. private:   
  10.     int a;   
  11. };   
  12. int main()   
  13. {   
  14.     typedef void (*PFUN)();   
  15.     PFUN pfun;   
  16.     //验证整个对象的内存模型,    
  17.     base t(3);   
  18.     cout << "对象的地址 " << (int*)(&t) << endl; //对象的地址   
  19.     cout << "base::a= " << *((int*)(&t)+1) << endl;   
  20.     //验证虚函数表的模型   
  21.     cout << "虚函数表的地址 " << (int*)(*(int*)(&t)) << endl;   
  22.     cout << "第一个虚函数的地址 " << *((int*)(*(int*)(&t))) << endl;   
  23.     cout << "第二个虚函数的地址 " << *((int*)(*(int*)(&t))+1) << endl;   
  24.     pfun = (PFUN)*((int*)(*(int*)(&t)));   
  25.     cout << "vptr[0] ";   
  26.     pfun();   
  27.     cout << "vptr[1] ";   
  28.     pfun = (PFUN)*((int*)(*(int*)(&t))+1);   
  29.     pfun();   
  30.     return 0;   
  31. }  

验证结果:

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值