消极的多态与积极的多态
消极的多态:
Point *ptr;
ptr=new Point2d;
其中,Point为基类,Point2d为Point类的派生类,这种多态称为消极的多态。这种多态形式在编译时期就已完成,ptr扮演一个输送机制,这样在程序的任何地方均可以使用ptr来指向任意一个派生类。他被称为消极的,是因为没有对派生类行程使用,只是单单的用基类指针指向派生类。
积极的多态:
ptr->z();
其中,z()为对虚函数的调用。这种多态成为积极的多态。这种多态形式在执行时期进行。他被称为积极的多态是因为其真正利用基类指针对派生类成员进行了调用。
为了实现积极的多态应该做什么?
ptr是一个基类指针,尽管在编译时期就通过消极的多态将它与派生类对象联系起来了,但这只是将派生类的地址赋予了基类指针,实际上在编译时期我们并不知道ptr指向的到底是基类还是派生类,需要做什么才能实现通过基类指针来实现调用所指向对象的正确版本的虚函数呢?
1.ptr所指对象的真实类型。即ptr到底是指向基类的对象还是指向派生类的对象,不同的指向将调用不同的虚函数z();
2.z()实体的位置。可能存在不止一个虚函数,如何找到正确的要调用的z()的地址。
解决问题1,需要在class中增加一个字符串或数字,指明class的类型。
解决问题2,需要在class中增加一个指针,指向某表格,表格中带有虚函数的执行期地址。
虚函数表格中的虚函数地址的构建:在编译时期就已经完成,执行期只需要找到这些地址。
对于ptr->z();
编译时期将该调用转化为:(*ptr->vptr[4])(ptr);
其中,vptr[4]表示z()在vptr所指向表格中的slot索引,在单一继承体系中,所有的z()全部都被放在vptr[4]的位置,因此唯一在执行器所需要做的,就是问题1,即确认ptr的指向,slot4到底指的是哪个一个z()的实体,是基类的还是派生类的。