深入理解C++虚函数

本文介绍了如何通过访问虚函数表和函数指针来调用虚函数,包括虚函数表的构造、虚函数的继承与覆盖、以及如何访问父类的私有虚函数。并通过实例代码展示实现过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

测试环境:vs2013,windows 7  32 位系统

1.虚函数是放在虚函数表中的,因此我们可以通过访问虚函数表来找到相应的虚函数入口地址,从而调用虚函数。

2.由于虚函数是放在虚函数表中的,所以在继承的时候,其会放到子类的虚函数表中(如果子类重写了父类中虚函数则父类中相应虚函数在子类的虚函数表中就会被覆盖)。
3.虚函数表中存放虚函数顺序是先父类的(如果子类重写了父类的则直接替换为子类的)再放子类的虚函数。值得强调的是在子类对象中通过虚函数表中也是可以访问父类私有的虚函数(前提是子类没有重写父类中相应的虚函数)

下面一段程序就是通过虚函数表和函数指针来访问虚函数。

#include <iostream>
using namespace std;

class A
{
private:
	virtual void  print()
	{
		cout << "A::print()" << endl;
	}
	virtual void go()
	{
		cout << "A::go()" << endl;
	}
};
class B :public A
{
	virtual void go()
	{
		cout << "B::go()" << endl;
	}
	virtual  void f()
	{
		cout << "B::f()" << endl;
	}
};

typedef void (*pFun) (void);//

void main()
{
	B b;
	pFun fun;
	cout << "A size:" << sizeof(class A) << endl;//结果是4  有一个指指向虚函数表的指针
	cout << "B size:" << sizeof(class B) << endl; // 结果是4  有一个指指向虚函数表的指针
	for (int i = 0; i < 3; i++)//一共有3个虚函数(子类覆盖了一个 go)
	{
		fun = (pFun)*((int *)*(int *)(&b) + i);
		fun();
	}
	cin.get(); //让程序等待下
}

从运行的结果来看,通过虚函数表也可以访问父类的私有虚函数virtual void  print(),virtual void go()已经被子类重写。

fun = (pFun)*((int *)*(int *)(&b) + i);// 这条语句的理解

如下图所示,首先取得0x00002500这个虚函数表的首地址值,不是取b的内存对象地址值0x00001234。首先获得对象b的内存地址0x00001234,将其转换为int * 指针类型,就是读取内存4个字节,(int *)(&b),然后再解引取出内存地址4个字节对应的值0x00002500(虚函数表的首地址值)再使用int * 将其转换int * 指针(从首地址开始读取四个字节),(int *)*(int *)(&b),然后再解引获得这四个字节的值转换为函数指针。加i是指针步长,每次移动四个字节。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值