通过指针访问虚函数表调用函数

环境: VS2019, Debug x86编译器
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Base {
public:
	virtual void func1() = 0;
	virtual void func2() = 0;
};

class Drived : public Base {
public:
	virtual void func1()
	{
		printf("Drived::%s()\n", __func__);
	}

	virtual void func2()
	{
		printf("Drived::%s()\n", __func__);
	}
};

typedef void(*Fun)();

int main()
{
	Base* pBase = new Drived();

	pBase->func1();
	
	// printf("sizeof(long) = %zu\n", sizeof(long));
	printf("0x%p\n", pBase);
	printf("0x%p\n", (int*)pBase);
	int ptr = (*(int*)pBase); // vfptr的地址
	Fun pF = (Fun)(*((int *)ptr + 1));
	pF();

	delete pBase;
	return 0;
}

运行结果:
在这里插入图片描述

如果是在x64编译器环境下则把int *换成long long *, 因为两者的偏移量不一致
我在x64环境下long的字节为4

__vfptr是函数指针数组,在x64下指针是8个字节,所以vfptr数组内的元素各占8字节,故需要使用long long指针,这样+1才会偏移8个字节,如果为int *,则+1偏移量是4

下面是传参函数环境与上一致

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

class Base {
public:
	virtual void func1() = 0;
	virtual void func2(int num) = 0;
};

class Drived : public Base {
public:
	virtual void func1()
	{
		printf("Drived::%s()\n", __func__);
	}

	virtual void func2(int num)
	{
		printf("Drived::%s(%d)\n", __func__, num);
	}
};

typedef void(__stdcall *Fun)(int); 
// 不太理解此处为何需要加stdcall
// 参考https://blog.csdn.net/sky1718/article/details/51004758加上后运行不报错了

int main()
{
	Base* pBase = new Drived();

	pBase->func1();
	
	// printf("sizeof(long) = %zu\n", sizeof(long));
	// printf("0x%p\n", pBase);
	printf("0x%p\n", (int *)pBase);
	int ptr = (*(int *)pBase);
	Fun pF = (Fun)(*((int *)ptr + 1));
	pF(10);

	delete pBase;
	return 0;
}

运行结果:
在这里插入图片描述

题外话

如果把Base的public改为private,那么使用vfptr仍然可以调用到private的函数
如果你只是把Drived的public改为private,则pBase->func1()不会报错,因为func1继承过来的就是public

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值