理解C++虚函数的实现

来源:互联网 发布:华兴数控编程实例 编辑:程序博客网 时间:2024/06/06 02:01

理解C++虚函数的实现

概述

每个含有虚函数的类都至少有一个与之对应的虚函数表,虚函数表中保存该类所有虚函数对应的函数指针。
举例:

这里写图片描述

说明:
当子类继承父类时,父类的虚函数表指针vptr也被继承。当子类重写父类的虚函数时,子类的vptr指向的虚函数表中对应的这个虚函数的指针即变成子类的虚函数地址。例如D::bar。

构造虚函数表

由上例可总结虚函数表的构造过程:
1. 拷贝基类的虚函数表;
2. 替换子类重写的虚函数指针;
3. 追加子类自己的虚函数指针;
备注:
该过程由编译器完成,因此可以说:虚函数替换过程发生在编译时。
vptr和虚函数表都是编译器生成的。

这里写图片描述

虚函数的调用过程

以如下程序为例:
这里写图片描述

编译器只知道pb是B*类型的指针,但不知道它具体指向的对象类型:pb可能指向的是B的对象,也可能指向的是D的对象。但无论B::bar还是D::bar在各自的虚函数表中的偏移位置是相等的。
所以,只要确定被调虚函数在虚函数表中的偏移值,待运行时,确定具体类型,并找到相应的vptr,就可找出真正应该调用的函数。
虚函数指针中的ptr部分为虚函数表中的偏移值(以字节为单位)加1。
B::bar是一个虚函数指针, 它的ptr部分内容为9,它在B的虚函数表中的偏移值为8(8+1=9)。
当程序执行到“pb->bar()”时,已经能够判断pb指向的具体类型了:
如果pb指向B的对象,可以获取到B对象的vptr,加上偏移值8((char*)vptr + 8),可以找到B::bar。
如果pb指向D的对象,可以获取到D对象的vptr,加上偏移值8((char*)vptr + 8) ,可以找到D::bar。
如果pb指向其它类型对象…同理…

动态绑定:在运行时间接调用绑定的函数来实现动态绑定。
C++的函数调用默认不使用动态绑定。要触发动态绑定,必须满足两个条件:
a. 只有指定为虚函数的成员函数才能进行动态绑定;
b. 必须通过基类类型的引用或指针进行函数调用;

1 0
原创粉丝点击