C++虚函数表

虚函数表

C++中虚函数是通过一张**虚函数表(Virtual Table)**来实现的,在这个表中,主要是一个类的虚函数表的地址表;这张表解决了继承、覆盖的问题。在有虚函数的类的实例中这个表被分配在了这个实例的内存中,所以当我们用父类的指针来操作一个子类的时候,这张虚函数表就像一张地图一样指明了实际所应该调用的函数。

C++编译器是保证虚函数表的指针存在于对象实例中最前面的位置(是为了保证取到虚函数表的最高的性能),这样我们就能通过已经实例化的对象的地址得到这张虚函数表,再遍历其中的函数指针,并调用相应的函数。

class Base {
public:
	virtual void f() { cout << "Base::f()" << endl; }
	virtual void g() { cout << "Base::g()" << endl; }
	virtual void h() { cout << "Base::h()" << endl; }
};

typedef void(*Fun)(void);

int main()
{
	Base b;
	Fun pFun = NULL;
	cout <<        (int*)(&b) << endl;
	cout <<       *(int*)(&b) << endl;
	cout << (Fun*)*(int*)(&b)  << endl;
	pFun = *(Fun*)*(int*)(&b);
	pFun();
	system("pause");
	return 0;
}

解释:

(int*)(&b): 用转换int*类型得到一个指向b首地址的指针(因为b是一个类,用int*得到地址是合理的),**首地址内容存放的是虚表指针,虚表指针指向的是虚函数表,虚函数表里面存的又是每个函数的指针,所以虚表指针类型是**或者Fun*类型
*(int*)(&b),这里解引用就可以得到虚表指针了,但是含有int*类型,结果会出现错误,
所以(Fun*)*(int*)(&b)转回来" ,就可以正确得到虚表指针指向的地址了,也就是虚函数表的首地址,虚函数表其实就是指针数组,所以得到首元素的地址
上一步解引用得到了虚表指针,再解引用虚表指针*(Fun*)*(int*)(&b)就得到了虚函表首元素的内容了,就是第一个虚函数指针。

缺点
访问非public的虚函数#
父类非public的虚函数同样会存在于虚函数表中,所以,我们同样可以使用访问虚函数表的方式来访问这些non-public的虚函数

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值