- 1、本文档共8页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
动态联编实现原理分析
动态联编实现原理分析所谓动态联编,是指被调函数入口地址是在运行时、而不是在编译时决定的。C++语言利用动态联编来完成虚函数调用。C++标准并没有规定如何实现动态联编,但大多数的C++编译器都是通过虚指针(vptr)和虚函数表(vtable)来实现动态联编。基本的思路是:(1)为每一个包含虚函数的类建立一个虚函数表,虚函数表的每一个表项存放的是个虚函数在内存中的入口地址;(2)在该类的每个对象中设置一个指向虚函数表的指针,在调用虚函数时,先采用虚指针找到虚函数表,确定虚函数的入口地址在表中的位置,获取入口地址完成调用。我们将从以下几个方面来考察动态联编的实现细节。1.虚指针(vptr)的存放位置虚指针是作为对象的一部分存放在对象的空间中。一个类只有一个虚函数表,因此类的所有对象中的虚指针都指向同一个地方。在不同的编译器中,虚指针在对象中的位置时不同的。两种典型的做法是:(1)在Visual C++中,虚指针位于对象的起始位置;(2)在GNU C++中,虚指针位于对象的尾部而不是头部。可通过下面的程序考察在Visual C++中,虚指针在对象中的位置。#include iostreamusing namespace std;int globalv;class NoVirtual{int i;public:void func(){coutno virtual functionendl;}NoVirtual(){i=++globalv;}};class HaveVirtual:public NoVirtual{public:virtual void func(){coutVirtual Functionendl;}};int main(){NoVirtual n1, n2;HaveVirtual h1, h2;unsigned long* p;coutsizeof(NoVirtual):sizeof(NoVirtual)endl;coutsizeof(HaveVirtual):sizeof(HaveVirtual)endl;p=reinterpret_castunsigned long*(n1);coutfirst 4 bytes of n1:p[0]endl;p=reinterpret_castunsigned long*(n2);coutfirst 4 bytes of n2:p[0]endl;p=reinterpret_castunsigned long*(h1);coutfirst 4 bytes of h1: 0xhexp[0]endl;p=reinterpret_castunsigned long*(h2);coutfirst 4 bytes of h2: 0xhexp[0]endl;}程序运行结果:从程序的输出结果中,可以得出以下两个结论。(1)可以清楚地的看到虚指针对类对象大小的影响。类NoVirtual不包含虚函数,因此类NoVirtual的对象中只包含数据成员i,所以sizeof(NoVirtual)为4。类HaveVirtual包含虚函数,因此类HaveVirtual的对象不近要包含数据成员i,还要包含一个指向虚函数表的指针(大小为4B),所以sizeof(HaveVirtual)为8。(2)虚指针如果不在对象的头部,那么对象h1和对象h2的头4个字节(代表整型成员变量i)的值应该是3和4。而程序结果显示,类HaveVirtual的两个对象h1和h2的头4个字节的内容相同,这个值就是类HaveVirtual的虚函数表所在地址。2.虚函数表(vtable)的内部结构虚函数表是为拥有虚函数的类准备的。虚函数表中存放的是类的各个虚函数的入口地址。那么,可以思考以下几个问题:(1)虚函数的入口地址是按照什么顺序存放在虚函数表中的呢?(2)不同的类(比如说父类和子类)是否可以共享同一张虚函数表的呢?(3)虚函数表是一个类的对象共享,还是一个对象就拥有一个虚函数表?(4)多重继承的情况下,派生类有多少个虚函数表呢?考察如下程序:#include iostreamusing namespace std;#define ShowFuncAddress(function) _asm{\mov eax, function}\_asm{mov p,eax}\coutAddress of #function: pendl;void showVtableContent(char* className, void* pObj, int index){unsigned long* pAddr=NULL;pAddr=reinterpret_castunsigned long*(pObj);pAddr=(unsigned long*)*pAddr
文档评论(0)