多态
什么是多态?
对不同类型的实体提供统一接口的一种方式称之为多态。
为什么要使用多态?
举个例子(例1):
这就是没有使用多态的效果,我们是想通过改变函数形参想要调用不同类中的实现函数,但是改变形参后,调用的仍然是Animal类型中的实现函数。
要解决这一问题就要使用多态对类的实现加以修饰。
多态的条件
- 父类有虚函数。
virtual 函数返回类型 [函数名]
{
//实现内容;
} - 子类重写虚函数。
要求:子类重写函数的返回值,参数,名称与父类中虚函数一致。 - 在主函数中用指针或引用调用虚函数。
了解的多态的实现条件,那我们将例1加以改进,观察多态带来的不同实现效果。
使用多态与未使用多态的结果对比:
虚函数
在探究虚函数本质之前,让我们先来观察一个现象
因为虚指针的存在,导致运行后的结果都比预期推断的结果要大出四个字节,虚指针是多态实现的关键。
虚指针
一旦有了虚函数,则会隐藏插入一个大小为4字节(32位下)的指针(__vfptr),即虚指针,一个类中无论有多少虚函数,都只有一个虚指针。
虚指针默认位于实例化对象的第一位,如下图:
__vfptr |
---|
私有数据成员1 |
私有数据成员2 |
… |
私有数据成员n |
虚指针的本质
虚指针的本质是指向一张虚表,这张虚表上存放着虚函数的地址,当子类重写父类虚函数时,子类虚函数地址会覆盖父类虚函数地址,即可实现多态。
图示:
注意:
- 构造函数不能为虚函数
- 不同的类中具有不同的虚指针