C++中的虚表(vtable)和虚指针(vptr)示例详解

1、每个有virtual函数(析构函数或成员函数)的C++类都有一个存放所有虚函数地址的vtable表,每个类的对象都有个指向该类vtable表的vptr指针变量;
2、在vc中,类的继承是在基类后面追加数据的形式进行继承的。
测试代码如下(在64位系统下的vs2013环境中测试的):

//==============================
//@file Polymorphism_eg.cpp
//Polymorphism Programming Exercise
//@author Jaxon Yi <yijianchen@yeah.net>
//20181120
//===============================
#include<iostream>
using namespace std;
//------------------------------------------------------
class Test
{
public:
    Test(int a) {data = a;}
//基类中的虚析构函数
    virtual ~Test() {cout<<"Test deconstruct"<<endl;}
//基类中的虚函数fun1
    virtual void fun1() {cout<<"Test virtual fun1"<<endl;}
//基类中的虚函数fun2
    virtual void fun2() {cout<<"Test virtual fun2"<<endl;}
    int data;
};

class Test1:public Test
{
public:
    Test1(int d1, int d2):Test(d2) {data1 = d1;data2 = d2;}
    int data1;
    int data2;
//派生类中的虚析构函数
    virtual ~Test1() {cout<<"Test1 deconstruct"<<endl;}
//派生类中的虚函数fun11,不是实现基类中的fun1的多态
    virtual void fun11() {cout<<"Test1 virtual fun11"<<endl;}
//派生类中的虚函数fun21,不是实现基类中的fun2的多态
    virtual void fun21() {cout<<"Test1 virtual fun21"<<endl;}
};

//指向函数的指针 
typedef void (*Fun)(void);

int main()
{
   cout<<"test in 32bit system"<<endl;

//定义对象子类对象obj
   Test1 obj(1,2);
   cout << "obj's Size = " << sizeof(obj) << endl;
   cout << "obj's Address = " << &obj << endl;
   
//测试(&obj + 1),(int*)(&obj+1)和*((int*)&obj+1)的区别
   cout<<"second Test1 object's address = "<<&obj + 1<<endl;
   cout<<"third Test1 object's address = "<<&obj + 2<<endl;
   cout<<"first Test1 object-Test1 obj:Base data address and data:        "<<(int*)&obj + 1<<"\t"<<*((int*)&obj + 1)<<endl;
   cout<<"first Test1 object-Test1 obj:Derivate data1 address and data1:"<<(int*)&obj + 2<<"\t"<<*((int*)&obj + 2)<<endl;
   cout<<"first Test1 object-Test1 obj:Derivate data2 address and data2:"<<(int*)&obj + 3<<"\t"<<*((int*)&obj + 3)<<endl;
   
//获得虚表指针,显示虚表中的内容
	cout << "Test1 obj:vptr address = " << (int*)&obj << "\t" << "vptr value(vtable address) = " << *((int*)&obj + 0) << endl;
	cout << "vtable value1(first virtual fun address) = " << *((int*)*(int*)((int*)&obj + 0) + 0) << endl;
	cout << "vtable value2(second virtual fun address) = " << *((int*)*(int*)((int*)&obj + 0) + 1) << endl;
	cout << "vtable value3(third virtual fun address) = " << *((int*)*(int*)((int*)&obj + 0) + 2) << endl;
	cout << "vtable value4(forth virtual fun address) = " << *((int*)*(int*)((int*)&obj + 0) + 3) << endl;
	cout << "vtable value5(fifth virtual fun address) = " << *((int*)*(int*)((int*)&obj + 0) + 4) << endl;
	cout << "vtable value6 = " << *((int*)*(int*)((int*)&obj + 0) + 5) << endl;
	cout << "vtable value7 = " << *((int*)*(int*)((int*)&obj + 0) + 6) << endl;

//定义函数指针pFun并赋初值
   Fun pFun = NULL;
//调用第二个virtual fun 
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
   pFun();
//调用第三个virtual fun
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);
   pFun();
//调用第四个virtual fun
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
   pFun();
//调用第五个virtual fun
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+4);
   pFun();
   return 0;
}
//=============================================

运行结果如下:
在这里插入图片描述
此时子类Test1的vtable表的结构如下:

子类Test1的虚析构函数virtual ~Test1()
父类Test的虚成员函数1virtual void fun1()
父类Test的虚成员函数2virtual void fun2()
子类Test1的虚成员函数11virtual void fun11()
子类Test1的虚成员函数21virtual void fun21()

将部分程序修改为:

//基类中的析构函数
     ~Test() {cout<<"Test deconstruct"<<endl;}
//派生类中的虚析构函数
    virtual ~Test1() {cout<<"Test1 deconstruct"<<endl;}     
//调用第一个virtual fun 
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+0);
   pFun();
//调用第二个virtual fun
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
   pFun();
//调用第四个virtual fun
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
   pFun();
//调用第五个virtual fun
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+4);

运行结果如下:
在这里插入图片描述
此时子类Test1的vtable表的结构如下:

父类Test的虚成员函数1virtual void fun1()
父类Test的虚成员函数2virtual void fun2()
子类Test1的虚析构函数virtual ~Test1()
子类Test1的虚成员函数11virtual void fun11()
子类Test1的虚成员函数21virtual void fun21()

将部分程序再次修改为:

//基类中的析构函数
    virtual ~Test() {cout<<"Test deconstruct"<<endl;}
//派生类中的虚析构函数
    //virtual ~Test1() {cout<<"Test1 deconstruct"<<endl;}     
//调用第二个virtual fun 
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+1);
   pFun();
//调用第三个virtual fun
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+2);
   pFun();
//调用第四个virtual fun
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+3);
   pFun();
//调用第五个virtual fun
   pFun = (Fun)*((int*)*(int*)((int*)&obj+0)+4);

运行结果如下:
在这里插入图片描述
此时子类Test1的vtable表的结构如下:

父类Test的虚析构函数virtual ~Test()
父类Test的虚成员函数1virtual void fun1()
父类Test的虚成员函数2virtual void fun2()
子类Test1的虚成员函数11virtual void fun11()
子类Test1的虚成员函数21virtual void fun21()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值