关于虚函数表的个人总结

原文:http://www.cnblogs.com/alexqdh/archive/2011/04/24/2026257.html

关于虚函数表的个人总结

1.虚函数表的创建:

一个类存在虚函数的时候,编译器会为这个类创建一个虚函数表,这个表由这个类的所有对象共同所有。
在创建这个类的类对象的时候将这个对象的前4个字节作为这项这个虚函数表的指针。即类对象的首地址中的内容存放的是虚函数表的地址。
虚函数表的首地址里面存放的是第一个虚函数的首地址,如果有多个虚函数,则第二个虚函数的地址即为第一个虚函数首地址加上偏移量,
地址如果用int*为单位表示的话偏移量加1,对于以16进制位表示的话则加4,(见下例,如果看着晕的话,不用看具体的,下面会有更加详细的解释).
----(int*)*(int*)*(int*)(&b)是第一个函数的地址,则第二个函数的地址是(int*)*((int*)*(int*)(&b)+1)或者(int*)*(int*)(*(int*)(&b)+4)----
  
  
01#include<iostream>
02using namespace std;
03class Base
04{
05public:
06    virtual void f()
07    {
08        cout << "Base::f" << endl;
09    }
10    virtual void g()
11    {
12        cout << "Base::g" << endl;
13    }
14    virtual void h()
15    {
16        cout << "Base::h" << endl;
17    }
18};
19int main()
20{
21    Base b;
22    Base b1;
23    cout<<"第一个类b的地址:"<<(int*)(&b)<<endl;
24    cout<<"第二个类b1的地址:"<<(int*)(&b1)<<endl;
25    cout<<"虚地址b:"<<(int*)*(int*)(&b)<<endl;
26    cout<<"虚地址b1:"<<(int*)*(int*)(&b1)<<endl;
27}
运行结果如下:



2.关于(int*)*(int*)*(int*)(&b)的解释

(int*)*(int*)*(int*)(&b)
(1)(&b)表示对对象取地址,返回的实际上是一个Base*类型的指针,也就是一个地址。
(2)(int*)(&b)强制将(Base*)类型转换成(int*)型指针,注意这里(int*)做的转换是从(Base*)到(int*)
    实际上cout<<(&b)<<endl;与cout<<(int*)(&b)<<endl;的结果是一样的实际上都是指向的同一个地址,只是指针类型不同
(3)*(int*)(&b)表示去int型指针指向地址中的内容,即虚函数表地址的16进制位数表示,现在要注意了,这里的内容实际上int型的16进制数。
(4)(int*)*(int*)(&b)的第一个(int*)表示将取到的int型地址转换成地址,即虚函数表的地址,与(2)里面的(int*)的作用不一样
  比如下面的几条语句:     
  
  
1int* p;
2//p=0x567890;
3p=(int*)0x567890;

  注释的地方是错误的关键就在于0x567890是一个十六进制数与地址无关,用(int*)可以将16进制数转化成地址,然后用指针p指向地址。

(5)*(int*)*(int*)(&b),表示取虚函数表中第一个地址中的内容,即虚函数表中存放的第一个函数的地址的十六进制数表示,是int型

(6)(int*)*(int*)*(int*)(&b),将表示第一个函数地址的16进制数转换成地址,即第一个函数的地址

(7)如果以地址为单位求下一个函数的地址则在地址后加4,如(int*)*(int*)(*(int*)(&b)+4)

  如果以int*为单位的话求系一个函数地址则直接加1,如(int*)*((int*)*(int*)(&b)+1)

3.如何通过虚函数表进行函数调用。

现在在原来的代码中定义一个函数指针。

1typedef void(*Fun)(void);//如果不用Fun声明p函数指针的话可以直接写麻烦的式子:void(*p)(void)=(Fun)(int*)*((int*)*(int*)(&b)+1);

在main函数中

调用函数f:

1Fun p=NULL;
2p=(Fun)(int*)*(int*)*(int*)(&b);
3p();

调用函数g

1p=(Fun)(int*)*((int*)*(int*)(&b)+1);//或者p=(Fun)(int*)*(int*)(*(int*)(&b)+4);
2p();

调用函数h 

1p=(Fun)(int*)*((int*)*(int*)(&b)+2);//或者p=(Fun)(int*)*(int*)(*(int*)(&b)+8);
2p();

结果:

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值