如何理解C++中的动态绑定
作者:网络转载 发布时间:[ 2014/5/26 13:20:18 ] 推荐标签:C++ 动态绑定 net
A::fA()
B::vfA()
A::emptyB()
A::vfAonly()
A::fA()
B::fB()
B::vfA()
B::vfB()
B::emptyA()
A::emptyB()
B::vfAonly()
|
分析:
我们通过模拟编译器的编译过程来进行解释。只看编译器是怎么编译带有标号的那些函数调用的行的。
行1. 在编译器眼中,p是一个纯粹的A类指针,跟他指向的B类对象没有任何联系。因此,当看到p->fA()时,编译器便去A的定义中寻找fA,找到了,于是生成调用代码。
行2. 这行如果不被注释,编译器去A的定义中寻找定义fB,但是找不到这个名字,便会输出错误信息。
行3. 编译器继续去A定义中寻找vfA,这次找到了,而且发现关键字virtual,于是,采用虚拟函数调用代码生成技术,根据vfA的偏移值,生成代码调用虚拟函数表中该偏移值指向的函数。特别指出的是,在静态编译期间,编译器只知道偏移值,并不知道运行时该偏移到底指向什么函数。实际效果是,因为运行时,p指向的是B对象,因此调用的是B的虚拟函数vfA().
行4. 这行如果不被注释,编译器去A的定义中寻找名字vfB,找不到,出错。记住第一条原则,编译器是静态编译,不知道p和类B有联系。
行5. 同4,找不到名字emptyA。
行6. 简单,找到名字emptyB.
行7. 简单,找到名字vfAonly。
行8. 从这里开始,函数由B类引用r调用。在编译器眼中,r是一个纯粹的B类引用,他不假设r和A有任何关系。因此这一行,编译器去B类定义寻找名字fA。由于B继承自A,包括所有A的public函数定义,编译器成功找到A::fA。
行9. 类似行8,找到B自身的函数定义fB。
行10. 类似行3,编译器生成代码调用虚拟函数表某偏移指向的函数。运行时该偏移指向B::vfA.
行11. 编译器生成代码调用虚拟函数表某偏移指向的函数。运行时该偏移指向B::vfB.
行12. 简单,找到名字emptyA.
行13. 简单,找到名字A::emptyB. 因为B继承自A。
行14. 编译器生成代码调用虚拟函数表某偏移指向的函数。运行时该偏移指向B::vfAonly. 为什么编译器知道指向的是B的虚拟函数vfAonly而不是A的非虚拟函数呢?这跟另一个静态编译规则,名字隐藏,有关。
继承类的作用域中如果有基类的同名函数,继承类中的名字将隐藏基类同名函数,因此这时,编译器看不见A::vfAonly。
相关推荐
更新发布
功能测试和接口测试的区别
2023/3/23 14:23:39如何写好测试用例文档
2023/3/22 16:17:39常用的选择回归测试的方式有哪些?
2022/6/14 16:14:27测试流程中需要重点把关几个过程?
2021/10/18 15:37:44性能测试的七种方法
2021/9/17 15:19:29全链路压测优化思路
2021/9/14 15:42:25性能测试流程浅谈
2021/5/28 17:25:47常见的APP性能测试指标
2021/5/8 17:01:11