6 多态 虚机制
6.1 虚机制
当类中有虚函数时(无论多少个),其就会多一个指针—— vptr 虚指针,其会指向一个 vtbl 虚函数表,而 vtbl 中有指针一一对应指向所有的虚函数
有三个类依次继承,其中A有两个虚函数 vfunc1()
vfunc2()
,B改写了A的 vfunc1()
,C又改写了B的 vfunc1()
,子类在继承中对于虚函数会通过指针的方式进行——因为可能其会被改写
继承中,子类要继承父类所有的数据和其函数调用权,但虚函数可能会被改写,所以调用虚函数是==动态绑定==的,通过指针 p
找到 vptr
,找到vtbl
,再找到调用的第n个虚函数函数——( *(p->vptr[n]) )(p)
编译器在满足以下三个条件时就会做==动态绑定==:
- 通过指针调用
- 指针是向上转型 up-cast ——
Base* basePtr = new Derived;
- 调用的是虚函数
编译器就会编译成 ( *(p->vptr[n]) )(p)
这样来调用
例如:用一个 Shape(父类)的指针,调用 Circle(子类)的 draw 函数(每个形状的 draw 都不一样,继承自 Shape)
多态:同样是 Shape 的指针,在链表中却指向了不同的类型
list<Shape*> Mylist
多态优点:代码组织结构清晰,可读性强,利于前期和后期的扩展以及维护
6.2 动态绑定
a.vfunc1()
是通过对象来调用,是 static binding 静态绑定
在汇编代码中,是通过 call 函数的固定地址来进行调用的
pa
是指针,是向上转型,是用其调用虚函数—— dynamic binding 动态绑定
在汇编代码中,调用函数的时候,蓝框的操作用 c语言 的形式即是 —— ( *(p->vptr[n]) )(p)
下面同理