验证C++中的虚函数表的存在

///从网上抄来的,做了点修改,能正确运行出来而已
#include <stdio.h>
#include <iostream>
using namespace std;

///基类,有2个成员变量width和height,有2个虚函数和一个成员函数
class Shape
{
public:
    Shape(int a = 0, int b = 0)
    {
        width = a;
        height =b;
    }
    
    virtual int area()
    {
        printf("Parent class area:\n");
        return 0;
    }
    
    virtual void sayHello()
    {
        printf("Shape..\n");
    }
    
    void bar()
    {
        printf("bar fun width:%d\n", width);
    }
    
protected:
    int width, height;
};

///Shape子类,继承了Shape的width和height,重写了虚函数area和sayHello,重新定义了一个虚函数Call,相当于有3个虚函数
class Rectangle:public Shape
{
public:
    Rectangle(int a = 0, int b = 0) : Shape(a, b){}
    int area()
    {
        printf("Rectangle class area:\n");
        return width * height;
    }

    virtual void sayHello()
    {
        printf("Rectangle..\n");
    }
    
    virtual void Call()
    {
        printf("Rectangle Call....\n");
    }
    
};

///Shape子类,继承了Shape的width和height,重写了虚函数area和sayHello,重新定义了一个虚函数Call,相当于有3个虚函数
class Triangle:public Shape
{
public:
    Triangle(int a = 0, int b = 0) : Shape(a, b){}
    int area()
    {
        printf("Triangle class area:\n");
        return width * height / 2;
    }

    virtual void sayHello()
    {
        printf("Triangle..\n");
    }
    
    virtual void Call()
    {
        printf("Triangle Call....\n");
    }
};

///多肽的调用接口
void test(Shape* shape)
{
    shape->bar();
    shape->area();
    shape->sayHello();
}

class Shape1
{
public:
    Shape1(int a = 0, int b = 0)
    {
        width = a;
        height =b;
    }
    
     int area()
    {
        printf("Parent class area:\n");
        return 0;
    }
    
     void sayHello()
    {
        printf("Shape..\n");
    }
    
    void bar()
    {
        printf("bar fun width:%d\n", width);
    }
    
protected:
    int width, height;
};

void test2(Shape* shape)
{
    printf("\n----\n");
    
    typedef void (*BAR_FUN)(void*);
    typedef int (*AREA_FUN)(void*);
    typedef void (*SAYHELLO_FUN)(void*);
    typedef void (*CALL_FUN)(void*);
    typedef void* ADDRESS;
    
    BAR_FUN bar_fun = (BAR_FUN)(&Shape::bar); ///bar成员函数为非虚函数
    bar_fun((void*) shape); ///调用bar函数,需要传入this指针就是shape
    
    ///前面8个字节存放的是虚函数表,先将虚表首地址(二级指针)强制转换成void** 类型
    ///虚表是二级指针,在首地址处
    ADDRESS* vtable_addr = *((ADDRESS**)(shape));///先将二级指针转换成一级指针,实现函数调用
    ADDRESS ptr = *(vtable_addr);///先获取到虚表的首地址
    AREA_FUN area_fun = (AREA_FUN)ptr; ///把虚函数area的首地址赋值给area_fun
    
    ///vtable_addr + 1的原因是获取sayhello_fun函数地址
    SAYHELLO_FUN sayhello_fun = (SAYHELLO_FUN)*(vtable_addr+1);
    
    ///vtable_addr + 2的原因是获取Call函数地址
    CALL_FUN  call_fun = (CALL_FUN)*(vtable_addr+2);
    
    area_fun((void*)shape);                ///传入this指针shape
    sayhello_fun((void*)shape);            ///传入this指针shape
    call_fun((void*)shape);                ///传入this指针shape
    
    printf("\n----\n");
    
}

int main()
{
    cout << sizeof(Shape) << endl;                ///16个字节
    cout << sizeof(Triangle) << endl;            ///16个字节
    cout << sizeof(Rectangle) << endl;            ///16个字节
    cout << sizeof(Shape1) << endl;                ///8个字节(没有加virtual关键字)
    ///说明写了virtual,C++编译器多分配了8个字节存放虚表,进行多肽,
    ///int width, height占了8个字节
    
    ///多肽
    Shape* shape = new Triangle(3, 4);
    ///test(shape);
    test2(shape);
    delete shape;
    
    ///多肽
    shape = new Rectangle(5, 6);
    ///test(shape);
    test2(shape);
    delete shape;
    
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值