网站大量收购独家精品文档,联系QQ:2885784924

C中构造函数中调用虚函数的问题.docVIP

  1. 1、本文档共5页,可阅读全部内容。
  2. 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
  3. 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  4. 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  5. 5、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  6. 6、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  7. 7、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  8. 8、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
C中构造函数中调用虚函数的问题

C++中构造函数中调用虚函数的问题 在构造函数中调用虚成员函数,虽然这是个不很常用的技术,但研究一下可以加深对虚函数机制及对象构造过程的理解。这个问题也和一般直观上的认识有所差异。先看看下面的两个类定义。 struct C180 {  C180() {   foo();   this-foo();  }  virtual foo() {   cout C180.foo this: this vtadr: *(void**)this endl;  } }; struct C190 : public C180 {  C190() {}  virtual foo() {   cout C190.foo this: this vtadr: *(void**)this endl;  } };   父类中有一个虚函数,并且父类在它的构造函数中调用了这个虚函数,调用时它采用了两种方法一种是直接调用,一种是通过this指针调用。同时子类又重写了这个虚函数。   我们可以来预测一下如果构造一个C190的对象会发生什么情况。   我们知道,在构造一个对象时,过程是这样的: 1) 首先会按对象的大小得到一块内存(在heap上或在stack上), 2) 把指向这块内存的指针做为this指针来调用类的构造函数,对这块内存进行初始化。 3) 如果对象有父类就会先调用父类的构造函数(并依次递归),如果有多个父类(多重继承)会依次对父类的构造函数进行调用,并会适当的调整this指针的位置。在调用完所有的父类的构造函数后,再执行自己的代码。   照上面的分析构造C190时也会调用C180的构造函数,这时在C180构造函数中的第一个foo调用为静态绑定,会调用到C180::foo()函数。第二个foo调用是通过指针调用的,这时多态行为会发生,应该调用的是C190::foo()函数。   执行如下代码: C190 obj; obj.foo();   结果为: C180.foo this: 0012F7A4 vtadr: 0045C404 C180.foo this: 0012F7A4 vtadr: 0045C404 C190.foo this: 0012F7A4 vtadr: 0045C400 和我们的分析大相径庭。第一行是在C180中运行foo()函数得到的,这里的foo()当然是调用C180中的foo()函数。第二行是调用C180中的this-foo()得到的,此时this指向的应该是C180的虚表地址,按照调用规则,应该是动态绑定,即,此时若派生类对该虚函数实现过,则应该调用派生类的虚函数,这里是一个例外,下面会详细讲到。 至此,C190的父类的构造函数运行完毕,转而运行C190的构造函数,但是这里C190的构造函数什么都没有。第三行是在main函数中调用obj.foo()得到的,这里直接进入C190运行就可以了。 这里必须注意一点,就是前两行和第三行的虚表是不同的,这是因为前两行的虚表是C180的虚表,而第三行的虚表是C190的虚表。 其实这正是奥秘所在。   为此我查了一下C++标准规范。在12.7.3条中有明确的规定。这是一种特例,在这种情况下,即在构造子类时调用父类的构造函数,而父类的构造函数中又调用了虚成员函数,这个虚成员函数即使被子类重写,也不允许发生多态的行为。即,这时必须要调用父类的虚函数,而不子类重写后的虚函数。   我想这样做的原因是因为在调用父类的构造函数时,对象中属于子类部分的成员变量是肯定还没有初始化的,因为子类构造函数中的代码还没有被执行。如果这时允许多态的行为,即通过父类的构造函数调用到了子类的虚函数,而这个虚函数要访问属于子类的数据成员时就有可能出错。   我们看看VC7.1生成的汇编代码就可以很容易的理解这个行为了。 这是C190的构造函数: 01 00426FE0 push ebp 02 00426FE1 mov ebp,esp 03 00426FE3 sub esp,0CCh 04 00426FE9 push ebx 05 00426FEA push esi 06 00426FEB push edi 07 00426FEC push ecx 08 00426FED lea edi,[ebp+FFFFFF34h] 09 00426FF3 mov ecx,33h 10 00426FF8 mov eax,0CCCCCCCCh 11 00426FFD rep stos dword ptr [edi] 12 00426FFF pop ecx 13 0042

文档评论(0)

wuyoujun92 + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档