virtual table 多态实现原理

转载请注明出处
blog.yesiare.cn

多态原理

在c++中,多态是通过一张虚函数表(virtual table)来实现的,简称v-table,在这个表中主要是一个类的虚函数地址,通过这张表来实现继承,覆写。
比如,一个父类有一个虚函数,这个虚函数地址放在v-table中,有一个子类继承了这个父类,并且覆写了这个虚函数,是如何复写的呢,由于虚函数表也继承了过来,就用新的虚函数地址将原来表中旧的替换掉,这样一来,通过父类指针指向子类的时候,就可以调用这个子类覆写过的虚函数,如果有不同子类都覆写了这个函数,那么只用父类指针就可以实现调用所有子类覆写过的函数,这就是c++的多态。

虚函数表(v-table)存放在哪

如果一个类包含虚函数,那么在这个类内存空间的开头,就存放着一个指向它虚函数表的指针,这个表类似一个指针数组,存放函数指针。
比如有这样一个类。

class A{
public:
    virtual void func1(){cout<<"i am A::func1"<<endl;}
    virtual void func2(){cout<<"i am A::func2"<<endl;}
    virtual void func3(){cout<<"i am A::func3"<<endl;}
    
    int data;
	int data2;
};

那么它在内存中的情况就是这样的
c++1
func1 是虚函数表中具体的函数指针 可以看着 * 型
ptovtable 就是指向虚函数表的指针 可以把它看作 ** 型
下面我们如何用代码来证明呢?

#include<iostream>
using namespace std;

class A{
public:
    virtual void func1(){cout<<"i am A::func1"<<endl;}
    virtual void func2(){cout<<"i am A::func2"<<endl;}
    virtual void func3(){cout<<"i am A::func3"<<endl;}

    int data;
    int data2;
};
int main(){
    //首先我们建立一个函数指针类型(无返无参,对应上面类中虚函数)
    typedef void (*Pf)(void);
    Pf f1,f2,f3;//一会用来放三个虚函数
    A a;//生成实例

    cout<<"对象的起始地址:"<<&a<<endl;  //out 0x69fef4
    //接下来要提取出 ptovtable,指针占4个字节(我的编译器是)
    //所以如下,先将a的地址转换成int* 这样解引用才能得到4个字节(因为int刚好四字节
    //然后将得到的地址转换成int**  看图,ptovtable 可看作**
    cout<<"vtable的起始地址: "<<(int **)*(int *)(&a)<<endl;//out 0x4850f8
    //现在我们已经得到vtable的起始地址了,下面 要提取第一个函数指针
    //将 ** 变成 *  解引用就行,第一个函数指针偏移是0
    cout<<"表中第一个位置存放的指针:"<<*((int **)*(int *)(&a)+0)<<endl;//out 0x42d790
    //我们得到了一个函数指针,但是别忘了,他现在还是int*型,而函数指针是 void(*)(void)型
    //so 再强转一下
    f1=(Pf)*((int **)*(int *)(&a)+0);
    f1();//out i am A::func1
    //其他的不用说了吧,表的结尾存放NULL
    cout<<"表中第二个位置存放的指针:"<<*((int **)*(int *)(&a)+1)<<endl;//输出自己看
    cout<<"表中第三个位置存放的指针:"<<*((int **)*(int *)(&a)+2)<<endl;//
    cout<<"表中第四个位置存放的指针:"<<*((int **)*(int *)(&a)+3)<<endl;//
    f2=(Pf)*((int **)*(int *)(&a)+1);
    f3=(Pf)*((int **)*(int *)(&a)+2);
    f2();
    f3();
    cout<<"by zsh"<<endl;
    return 0;
}

运行情况
c2
呼~ 打完收工
注意平时用不到这个,知道这个东西就好
有什么意义呢,加深理解把
装完b就跑

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值