WHCSRL 技术网

对于C++中多态的理解_amuro

概述

OOP或者OOD的概念中,包含有复合composition,委托delegation和继承inheritance三种关系。其中最复杂的就是inheritance。

继承时,子类Derived Class继承的是:

  • 父类Base Class的所有数据
  • 父类所有函数的调用权

体现inheritance精髓的就是多态了。
这里有几个概念基本是等效的 多态 = 虚函数 = 动态绑定

函数的调用方式

在汇编语言中,函数的调用是通过CALL指令实现的。
在C++中,根据CALL指令后面的参数,函数的调用分为动态绑定和静态绑定两种。

静态绑定

普通的函数,在编译链接后,就确定了其调用地址。所谓静态绑定,就是函数的地址是在链接阶段确定了,无需等到运行时重新计算。
体现为 call address_xxx 的形式

动态绑定

动态绑定则是在运行时才确定函数的调用地址。在C++中,虚函数的调用就是通过这种方式实现的。

动态绑定的条件

  1. 通过指针进行调用
  2. 指针是up cast的,即声明时是按照父类Base Class,但new的时候是子类Derived Class的对象
  3. 调用的是虚函数

多态的用法

动态绑定技术也被称为多态,即一种函数名称(虚函数名),多种形态(虚函数的实体由不同的子类实现)。
典型的用法是,通过将同一各基类的不同子类的指针放到一组容器中,容器以基类指针为类型,通过指针调用不同子类的虚函数的实现

C++中多态的实现

C++在实现多态时,使用了虚指针vptr+虚表vtable的方式。

  1. 若类中存在1…n个的虚函数,则类的对象的内存空间中存在一个虚指针vptr指向一个虚表vtbl
  2. 虚表vtbl由该类所有虚函数的函数地址构成,存放类中所有虚函数的指针
    • 若父类的虚函数未被重写override,则该虚函数地址为父类虚函数地址
    • 若父类的虚函数被重写override,则该虚函数地址为子类虚函数地址
  3. 子类中的虚表的虚函数的顺序严格与父类一致,以利于通过动态绑定的方式进行寻址
  4. 最后一个表元素为0

在这里插入图片描述

动态绑定的调用方式

p为指向对象的指针,最终动态绑定的虚函数被编译为 (*(p->vptr)[n])§;
最后的§表示p作为this指针被传入。

参考

侯捷老师的C++程序设计(II)

推荐阅读