c++中的虚函数及虚函数表

一、虚函数的定义

有关键字virtual修饰的成员函数,为了实现多态。

二、虚函数表

1.虚函数表用来存放虚函数的地址,也称虚表。
2.一个含有虚函数的类中至少有一个虚表。
3.虚表指针:二级指针,虚函数指针的指针,存放在对象模型头部,32位系统中占4个字节,在64位系统中占8个字节。虚表指针中存放着虚表的首地址。可以通过对象实例化的地址得到虚函数表的地址。
4.虚表与虚表指针的关系如下:
在这里插入图片描述

三、子类中的虚表

1.单继承无虚函数覆盖:

class Base
{
public:
	virtual void Func1()
	{
		cout << "Base::Func1" << endl;

	}
	virtual void Func2()
	{
		cout << "Base::Func2" << endl;

	}

};


class Derive :public Base
{
public:
	virtual void Func3()
	{
		cout << "Derive::Func3" << endl;

	}
	virtual void Func4()
	{
		cout << "Derive::Func4" << endl;
	}
};


typedef void(*VFPTR)();
//打印虚函数表
void PrintVF(VFPTR* VFaddress)
{
	cout << "虚表地址:" << VFaddress << endl;
	int i = 1;
	VFPTR vfunc = VFaddress[0];
	while (vfunc != nullptr)
	{
		cout << "第" << i << "个虚函数地址:" << vfunc << endl;
		vfunc();
		VFaddress++;
		vfunc = *VFaddress;
		i++;
	}
}

int main()
{

	Base b;
	Derive d;
	cout << "父类虚表:" << endl;
	PrintVF((VFPTR*)*(int*)&b);
	cout << "子类虚表:" << endl;
	PrintVF((VFPTR*)*(int*)&d);
	system("pause");
	return 0;
}

在这里插入图片描述
在这里插入图片描述
单继承时,子类中只有一个虚函数表,父类虚函数在前,子类虚函数在后,按照声明顺序存放。
在这里插入图片描述

2.单继承有虚函数覆盖

class Base
{
public:
	virtual void Func1()
	{
		cout << "Base::Func1" << endl;

	}
	virtual void Func2()
	{
		cout << "Base::Func2" << endl;
	}
};
class Derive :public Base
{
public:
	virtual void Func1()
	{
		cout << "Derive::Func1" << endl;

	}
	virtual void Func2()
	{
		cout << "Derive::Func2" << endl;

	}

	virtual void Func3()
	{
		cout << "Derive::Func3" << endl;

	}
	virtual void Func4()
	{
		cout << "Derive::Func4" << endl;
	}
};

void PrintVF(VFPTR* VFaddress)
{
	cout << "虚表地址:" << VFaddress << endl;
	int i = 1;
	VFPTR vfunc = VFaddress[0];
	while (vfunc != nullptr)
	{
		cout << "第" << i << "个虚函数地址:" << vfunc << endl;
		vfunc();
		VFaddress++;
		vfunc = *VFaddress;
		i++;
	}
}

int main()
{
	Base b;
	Derive d;
	cout << "父类虚表:" << endl;
	PrintVF((VFPTR*)*(int*)&b);
	cout << "子类虚表:" << endl;
	PrintVF((VFPTR*)*(int*)&d);
	system("pause");
	return 0;
}

在这里插入图片描述
子类中有一个虚函数表,覆盖的虚函数放在虚函数表中继承于父类的位置,新增的虚函数放在继承的父类虚表的后面。
在这里插入图片描述

3.多继承没有虚函数重写:


class Base1
{
public:
	virtual void Func1()
	{
		cout << "Base1::Func1" << endl;

	}
	virtual void Func2()
	{
		cout << "Base1::Func2" << endl;

	}

};

class Base2
{
public:
	virtual void Func1()
	{
		cout << "Base2::Func1" << endl;

	}
	virtual void Func2()
	{
		cout << "Base2::Func2" << endl;

	}

};

class Derive :public Base1, Base2
{
public:

	virtual void Func3()
	{
		cout << "Derive::Func3" << endl;

	}
	virtual void Func4()
	{
		cout << "Derive::Func4" << endl;

	}

};


typedef void(*VFPTR)();
void PrintVF(VFPTR* VFaddress)
{
	cout << "虚表地址:" << VFaddress << endl;
	int i = 1;
	VFPTR vfunc = VFaddress[0];
	while (vfunc != nullptr)
	{
		cout << "第" << i << "个虚函数地址:" << vfunc << endl;
		vfunc();
		VFaddress++;
		vfunc = *VFaddress;
		i++;
	}
}


int main()
{

	Base1 b1;
	Base2 b2;
	Derive d;

	cout << "父类虚表(Base1):" << endl;
	PrintVF((VFPTR*)*(int*)&b1);
	cout << "父类虚表(Base2):" << endl;
	PrintVF((VFPTR*)*(int*)&b2);

	cout << "Derive ::Base1:" << endl;
	PrintVF((VFPTR*)*(int*)&d);
	cout << "Derive ::Base2:" << endl;
	PrintVF((VFPTR*)(*(int*)((char*)&d + sizeof(Base1))));

	system("pause");
	return 0;
}

在这里插入图片描述
在这里插入图片描述
多继承时,子类中虚表个数等于直接父类的个数,子类中新增的虚函数放在第一个直接父类的虚表末尾,按照声明顺序存放。

4.多继承有虚函数重写时

class Base1
{
public:
	virtual void Func1()
	{
		cout << "Base1::Func1" << endl;

	}
	virtual void Func2()
	{
		cout << "Base1::Func2" << endl;

	}

};

class Base2
{
public:
	virtual void Func1()
	{
		cout << "Base2::Func1" << endl;

	}
	virtual void Func2()
	{
		cout << "Base2::Func2" << endl;

	}

};

class Derive :public Base1, Base2
{
public:

	virtual void Func1()
	{
		cout << "Derive::Func1" << endl;

	}
	virtual void Func3()
	{
		cout << "Derive::Func3" << endl;

	}
	virtual void Func4()
	{
		cout << "Derive::Func4" << endl;

	}

};


typedef void(*VFPTR)();
void PrintVF(VFPTR* VFaddress)
{
	cout << "虚表地址:" << VFaddress << endl;
	int i = 1;
	VFPTR vfunc = VFaddress[0];
	while (vfunc != nullptr)
	{
		cout << "第" << i << "个虚函数地址:" << vfunc << endl;
		vfunc();
		VFaddress++;
		vfunc = *VFaddress;
		i++;
	}
}


int main()
{

	Base1 b1;
	Base2 b2;
	Derive d;

	cout << "父类虚表(Base1):" << endl;
	PrintVF((VFPTR*)*(int*)&b1);
	cout << "父类虚表(Base2):" << endl;
	PrintVF((VFPTR*)*(int*)&b2);

	cout << "Derive ::Base1:" << endl;
	PrintVF((VFPTR*)*(int*)&d);
	cout << "Derive ::Base2:" << endl;
	PrintVF((VFPTR*)(*(int*)((char*)&d + sizeof(Base1))));

	system("pause");
	return 0;
}

在这里插入图片描述
在这里插入图片描述
多继承有虚函数重写时,子类中虚表个数等于直接父类的个数,子类中重写的虚函数覆盖继承的父类的虚函数,子类中新增的虚函数放在第一个直接父类的虚表末尾,按照声明顺序存放。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值