设为首页 加入收藏

TOP

C/C++虚函数实现的基本原理
2019-01-03 20:09:03 】 浏览:46
Tags:C/C 函数 实现 基本 原理

简单地说,每一个含有虚函数(无论是其本身的,还是继承而来的)的类都至少有一个与之对应的虚函数表,其中存放着该类所有的虚函数对应的函数指针。例:


其中:


提示:为了描述方便,本文在探讨对象内存布局时,将忽略内存对齐对布局的影响。


从编译器的角度来说,B的虚函数表很好构造,D的虚函数表构造过程相对复杂。下面给出了构造D的虚函数表的一种方式(仅供参考):


提示:该过程是由编译器完成的,因此也可以说:虚函数替换过程发生在编译时。


以下面的程序为例:


编译器只知道pb是B*类型的指针,并不知道它指向的具体对象类型 :pb可能指向的是B的对象,也可能指向的是D的对象。


但对于“pb->bar()”,编译时能够确定的是:此处operator->的另一个参数是B::bar(因为pb是B*类型的,编译器认为bar是B::bar),而B::bar和D::bar在各自虚函数表中的偏移位置是相等的。


无论pb指向哪种类型的对象,只要能够确定被调函数在虚函数中的偏移值,待运行时,能够确定具体类型,并能找到相应vptr了,就能找出真正应该调用的函数。


提示:本人曾在“C/C++杂记:深入理解数据成员指针、函数成员指针”一文中提到:虚函数指针中的ptr部分为虚函数表中的偏移值(以字节为单位)加1。


B::bar是一个虚函数指针, 它的ptr部分内容为9,它在B的虚函数表中的偏移值为8(8+1=9)。


当程序执行到“pb->bar()”时,已经能够判断pb指向的具体类型了:


当一个类继承多个类,且多个基类都有虚函数时,子类对象中将包含多个虚函数表的指针(即多个vptr),例:


其中:D自身的虚函数与B基类共用了同一个虚函数表,因此也称B为D的主基类(primary base class)。


虚函数替换过程与前面描述类似,只是多了一个虚函数表,多了一次拷贝和替换的过程。


虚函数的调用过程,与前面描述基本类似,区别在于基类指针指向的位置可能不是派生类对象的起始位置,以如下面的程序为例:


本文不讨论菱形继承的情形,个人觉得:菱形继承的复杂度远大于它的使用价值,这也是C++让人又爱又恨的原因之一。



编程开发网
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇C 语言中的结构体和共用体(联合.. 下一篇Python网络编程socket模块实例解析

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

array(4) { ["type"]=> int(8) ["message"]=> string(24) "Undefined variable: jobs" ["file"]=> string(32) "/mnt/wp/cppentry/do/bencandy.php" ["line"]=> int(214) }