上次说到,多态机制依靠虚函数来实现。编译器看到virtual关键字,变进行动态绑定。
典型的编译器对每个包含虚函数的类创建一个表,称为虚函数表(v-table)。编译器放置特定类的虚函数的地址。在每个带有虚函数的类中,编译器秘密地放置一个指针(vpointer),指向这个对象的虚函数表。当通过基类指针做虚函数调用时,编译器静态地插入一些代码,这些代码完成两个功能,一是取得这个指向虚函数表的指针,而是在虚函数表中查找真正需要调用的函数的地址,这样就能调用正确的函数并引起动态绑定的发生。
上一次主要用程序来演示了vpointer在类实例中的位置、虚函数表的地址以及虚函数表中存放的函数指针。这次仍然通过程序来说明当实现继承和重新定义一些虚函数时所发生的事情。
看图说话:用基类的指针指向子类的对象,其虚函数表地址实为子类的虚函数表地址。并且子类中重写的虚函数的地址覆盖了基类对应虚函数的地址。所以我们能通过基类的指针或引用来调用不同子类的函数。另外,对子类中新增加的虚函数是无法通过基类指针做函数调用的。
最后,总结一些注意事项:
1、虚函数必须在继承的情况下使用。
2、若基类中有一个虚函数,那它所派生的所有子类中所有函数名、参数、返回值都相同的成员方法都是虚函数,不论它们的声明前是否有Virtual关键字。
3、只有类的成员方法才能声明为虚函数,但是:静态、内联、构造除外。
4、析构函数建议声明为虚函数。
5 、调用虚函数时,必须要通过基类对象的指针或者引用来完成调用,否则无法发挥虚函数的特性。
6、调用虚函数时,传递不同类实例的指针,则对应不同的虚函数表。