【C++】多态机制的剖析!!!

本文详细介绍了C++中实现多态的条件及原理,包括虚函数表的作用及如何通过虚函数实现多态。此外,还深入探讨了带有虚拟继承的多态实现方式,特别是针对菱形继承情况下避免二义性的解决方法。

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

C++里面实现多态需要两个条件:1、基类里面的函数为虚函数,并且在派生类里面对基类里面的虚函数进行重写

     2、通过基类的指针或者引用来进行调用

虚函数:因为在使用虚函数的时候会在对象的里面添加一张虚函数表,用来存储类里面的虚函数的地址。


但是在这里,虚表的最后面不一定是0x00000000,这个和使用的编译器有关系。

如果在派生类里面对基类里面的虚函数进行重写的话,在基类里面就会对基类的虚表相同偏移量的函数进行替换,这样在通过基类的指针或者引用进行调用的时候就会调用派生类里面的函数,而不是基类里面的函数


这样在调用函数的时候就会调用重写之后的函数,依照这种机制就可以实现简单的多态。



带虚拟继承的多态:

虚拟继承是依靠偏移量表来实现的,在多态的实现里面,稍微复杂一点。

举个栗子:

class B
{
public:
	int _b;
	virtual void Test()
	{
		cout<<"B::Test()"<<endl;
	}
	virtual void Test1()
	{
		cout<<"B::Test1()"<<endl;
	}
};
class C:virtual public B
{
public:
	int _c1;
	virtual void Test()
	{
		cout<<"C::Test()"<<endl;
	}
	virtual void Test2()
	{
		cout<<"C::Test2()"<<endl;
	}
};
代码存储模型如下:


在重写虚函数之后在调用的时候就会嗲用派生类的虚函数,而且在菱形继承里面也不会出现二义性的问题。



菱形虚拟继承的剖析:



代码如下:

class B
{
public:
	int _b;
	virtual void Test()
	{
		cout<<"B::Test()"<<endl;
	}
	virtual void Test1()
	{
		cout<<"B::Test1()"<<endl;
	}
};
class C1:virtual public B
{
public:
	int _c1;
	virtual void Test()
	{
		cout<<"C1::Test()"<<endl;
	}
	virtual void Test2()
	{
		cout<<"C1::Test2()"<<endl;
	}
};

class C2:virtual public B
{
public:
	int _c2;
	virtual void Test()
	{
		cout<<"C2::Test()"<<endl;
	}
	virtual void Test3()
	{
		cout<<"C2::Test3()"<<endl;
	}
};
class D:public C1,public C2
{
public:
	int _d;
	virtual void Test()
	{
		cout<<"D::Test()"<<endl;
	}
	virtual void Test4()
	{
		cout<<"D::Test4()"<<endl;
	}
};



C1和C2的存储模型:


如果在C1或者C2里面没有定义虚函数,那么在C1或者C2里面就没有自己的虚表指针。


D类的模型:


在这里需要注意,这里的偏移量表指针的第一个数据不是0而是-4,因为在这里偏移量表指针的第一个数据是相对于自己的偏移量,在偏移量指针前面还存在着虚表指针。

这里同样的,如果D里面没有自己特有的虚函数,那么D就没有自己的虚表指针。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值