C++的多态的理解

多种状态,多种形态,同一个东西,在不同的环境下,会呈现出不同的状态。具体点就是去完成某个行为,当不同的对象完成时会产生不同的形状。

多态的实现

实现多条的3个条件
1、继承,多个子类一个父类。
2、父类有虚函数,子类重写父类的虚函数。
3、父类指针指向子类对象(一个函数,函数的形参是父类的指针,实参是子类对象的地址)。
虚函数:就是函数名前加virtual
多态实现的原理
虚函数:就是函数名前加virtual

多态实现的原理

在这里插入图片描述现在我们想知道:为什么父类指针指向子类对象(只能访问到子类从父类继承过来的成员)但是最终调用的是子类重写后的虚函数而不是从父类那里继承的?
理解以上问题,首先需要知道虚函数表和虚函数指针的概念。
虚函数表(函数(虚函数)指针数组):只要一个类有虚函数,那么这个类就会有一个虚函数表,存放这个类的所有的虚函数的入口地址。
虚函数表指针:有虚函数的类创建的对象的前四个字节(32位)是虚函数表的首地址

#include <iostream>
using namespace std;

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

private:
	int _b = 1;
};

int main()
{
	Base base;
	cout << sizeof(base) << endl;
}

在这里插入图片描述
上图可以看出来,基类中存在虚函数,计算基类的对象的大小为8,这是为什么呢?就是因为除了成员_b意外,还有一个_vfptr放在对象前面,_vfptr是一个指针,叫做虚函数表指针(虚表的地址),虚函数表里面存的是虚函数的地址,表是一个函数指针数组,里面存的是函数指针。
在这里插入图片描述
基类的类对象的虚函数指针指向虚函数表,虚函数表再去调用不同的函数。

在这里插入图片描述
子类重写父类的虚函数,子类的对象的虚函数指针指向虚函数表中的函数的入口地址,所以只要将子类的虚函数表的入口地址变为需要调用的子类的虚函数,而不是从父类继承的虚函数,知道了该调用那个虚函数后,就能够实现多态了。

在这里插入图片描述
我们可以通过通过调用父类的指针指向子类的对象来实现,就可以将子类的虚函数表的入口地址变为需要调用的子类的虚函数,就可以实现多态了。

代码演示

#include <iostream>
using namespace std;

//形状类:求面积   属性:面积

//圆类   求面积  属性:半径  面积
//矩形类  求面积  属性:宽 高  面积
class Shape
{
public:
	Shape()
	{
		s = 0;
		cout << "Shape()" << endl;
	}
	~Shape()
	{
		cout << "~Shape()" << endl;
	}
	virtual float getArea()
	{
		cout << "Shape getArea" << endl;
		return s;
	}
	
protected:
	float s;  //面积
};

class Circle :public Shape
{
public:
	Circle(float _r = 10)
	{
		r = _r;
		cout << "Circle(float)" << endl;
	}
	~Circle()
	{
		cout << "~Circle()" << endl;
	}
	virtual float getArea()
	{
		cout << "Circle getArea" << endl;
		s = 3.14 * r * r;
		return s;
	}
	
private:
	float r; //半径
};


class Rectangle :public Shape
{
public:
	Rectangle(float _w = 5, float _h = 5)
	{
		w = _w;
		h = _h;
		cout << "Rectangle(float)" << endl;
	}
	~Rectangle()
	{
		cout << "~Rectangle()" << endl;
	}
	virtual float getArea()
	{
		cout << "Rectangle getArea" << endl;
		s = w * h;
		return s;
	}
private:
	float w;  //宽
	float h;  //高
};

void calArea(Circle *shape)
{
	cout << "面积是:" << shape->getArea() << endl;
}

void calArea(Rectangle *shape)
{
	cout << "面积是:" << shape->getArea() << endl;
}


int main()
{
	//调用同一个函数,传入不同的形状对象,执行不同的计算面积的函数
	Circle circle;
	calArea(&circle);

	Rectangle rect;
	calArea(&rect);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哈哈吓

您的打赏是我创作的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值