多态
多态的定义:
多态就是不同对象对同一行为会有不同的状态。(举例 : 学生和成人都去买票时,学生会打折,成人不会)
实现多态有两个条件:
- 一是虚函数重写,重写就是用来设置不同状态的
- 二是对象调用虚函数时必须是指针或者引用
ps:没有这两个条件无法构成多态,很多笔试题都会利用这个陷阱让你上当!
实际上,代码上体现(动态)多态就是当父类指针指向子类对象,然后通过父类指针能调用子类的成员函数。
什么是虚函数?什么是重写?
- 虚函数是带有virtual关键字的成员函数
- 子类有个和父类完全相同(函数名,形参,返回值都相同,协变和析构函数除外)的虚函数,就称子类虚函数重写父类虚函数
多态的原理
多态是用虚函数表实现的。
有虚函数的类都会生成一个虚函数表,这个表在编译时生成。
虚函数表是一个存储虚函数地址的数组,以NULL结尾。
如果要生成子类虚表,就要经过三个步骤:
第一步,将父类虚表内容拷贝到子类虚表上;
第二步,将子类重写的虚函数覆盖掉表中父类的虚函数;
第三步,如果子类有新增加的虚函数,按声明次序加到最后
所以,多态的实现借助了虚函数以及虚函数表,那么在函数调用的时候它是如何实现多态的呢?
虚函数调用时,它会根据对象的虚函数表查找相应的虚函数地址从而调用相应的函数,换句话说,就是在调用函数时才确定具体需要调用哪个函数(动态绑定),从而实现多态,而不满足多态的函数在编译的时候就已经确定了函数的地址(静态绑定)。
图解虚函数表
- 父类虚函数表
- 子类虚函数实现
-子类虚函数表
我们从图中可以看出以下几点:
1)覆盖的f()函数被放到了虚函数表中原来父类虚函数的位置
2)没有被覆盖的函数依旧
3)新定义的虚函数按顺序放到了最后