c++虚函数与虚表初步

2020-04-24  本文已影响0人  FakeCSer爱去网吧

虚指针与虚表

代码:通过函数指针访问类对象中的虚函数表,来调用虚表中的虚函数
#include <iostream>
using namespace std;
class A
{
public:
    virtual void Fun(){cout<<"this is A::Fun()"<<endl;}
    virtual void Fun1(){cout<<"this is A::Fun1()"<<endl;}
};

typedef void (*F)();
F vfunc;//定义和声明函数指针

int main()
{
    A a;
//获取对象首地址(即虚表指针)
    long * vptrAddress = (long *)(&a);
    cout << vptrAddress<<endl;
//获取虚表的首地址
    long* vfunAddress = (long*)*vptrAddress;
    cout << vfunAddress<<endl;

//用函数指针直接调用地址的方法调用类中的函数
//  vfunc = (F)*((long*)*(long*)(&a));
    vfunc = (F)*(long*)vfunAddress; 
    vfunc();
//指针指向虚表下一个函数的地址,赋给函数指针来进行调用
    vfunc = (F)*((long*)vfunAddress+1);
    vfunc();
    return 0;
}

注意地址要用long *来存,不然存不下,指向不知道什么地方造成段错误
因为64位机器上,指针是8字节的(64/8),所以用long,在32位机器上,地址是4字节
运行结果:



又学到一个牛逼的方法
long** pVtab= (long**)&a;来操作
此时pVtab[0]就是虚函数表地址,pVtab[1]依次往下就是成员变量,注意内存对齐,如果成员有连续两个int,取到的就是一个不想要的值

#include <iostream>
using namespace std;
class A
{
public:
    virtual void Fun(){cout<<"this is A::Fun()"<<endl;}
    virtual void Fun1(){cout<<"this is A::Fun1()"<<endl;}
    A(int MEM,int MEM1)
        :mem(MEM),mem1(MEM1){}  
public:
    int mem;
    long mem1;
};

typedef void (*F)(void);
F vfunc;//定义和声明函数指针
A a(10,20);

long** pVtab = (long**)&a;

int main()
{
    vfunc = (F)pVtab[0][0];
    vfunc();
    
    vfunc = (F)pVtab[0][1];
    vfunc();
//access mem
    cout << "mem="<<(long)pVtab[1]<<endl;
    cout << "mem1="<<(long)pVtab[2]<<endl;
    
    return 0;
}

今天学习this指针的时候又在原程序上加了些功能

#include <iostream>
using namespace std;
class A
{
    public:
        virtual void Fun(){cout<<"this is A::Fun()"<<endl;}
        virtual void Fun1(){cout<<"this is A::Fun1()"<<endl;}
        A(int MEM,int MEM1)
            :mem(MEM),mem1(MEM1){}  
        void showThis(){cout<<"this pointer: " << "\t"<< hex << this << endl;}
    public:
        int mem;
        long mem1;
};

typedef void (*F)(void);
F vfunc;//定义和声明函数指针
A a(10,20);

long** pVtab = (long**)&a;

int main()
{
    //access function member
    vfunc = (F)pVtab[0][0];
    vfunc();

    vfunc = (F)pVtab[0][1];
    vfunc();
    //access data member
    cout << "mem="<< (long)pVtab[1] << endl;
    cout << "mem1="<< (long)pVtab[2] << endl;
    cout << "addr of vp: " << "\t" << hex << &pVtab[0] << endl; 
    cout << "addr of a: " << "\t" << hex << &a << endl;
    a.showThis();
    return 0;
}

可见,this指针指向的地址==对象的首地址(对象的位置)==虚指针的位置

上一篇下一篇

猜你喜欢

热点阅读