设为首页 加入收藏

TOP

12.2 多重继承(2)
2013-10-07 14:30:39 来源: 作者: 【 】 浏览:52
Tags:12.2 多重 继承

12.2 多重继承(2)

根据图12-7所示,对象SofaBed占用的内存空间大小为0x18字节。这些数据的内容是什么?它们又是如何存放在内存中的?具体如图12-8所示。

 
(点击查看大图)图12-8 对象SofaBed的内存信息
如图12-8所示,对象SofaBed的首地址在0x0012FF5C处,在图中可看到子类的数据成员和两个父类中的数据成员。数据成员的排列顺序由继承父类的先后顺序所决定,从左向右依次排列。除此之外,还剩余两个地址值,分别为0x00426198与0x0042501C,这两个地址处的数据如图12-9所示。
 
(点击查看大图)图12-9 子类对象的虚表指针对应的虚表信息

图12-9中显示了Debug下两个虚表指针所指向的虚表信息。查看图12-9中的两个虚表信息后会发现,这两个虚表中保存了子类的虚函数与父类的虚函数,父类的这些虚函数都是在子类中没有实现的。由此可见,编译器将子类CSofaBed的虚函数制作了两份。为什么会产生两份虚函数呢?我们先从对象SofaBed的构造入手,循序渐进地进行分析,过程如代码清单12-9所示。

代码清单12-9 对象SofaBed的构造过程—Debug版

  1. // 源码参考见代码清单12-7  
  2.     CSofaBed SofaBed;   // 定义对象  
  3. 0040F72D    lea     ecx,[ebp-24h]   ; 传递this指针  
  4. 0040F730    call    @ILT+10(CSofaBed::CSofaBed) (0040100f)    ; 调用构造函数  
  5. // 分析构造函数CSofaBed  
  6.     CSofaBed(){  
  7.     ; 部分代码分析略  
  8. 004011FE    pop     ecx     ; 还原this指针  
  9. 004011FF    mov     dword ptr [ebp-10h],ecx  
  10. 00401202    mov     ecx,dword ptr [ebp-10h]     ; 以对象首地址作为this指针  
  11. 00401205        call    @ILT+110(CSofa::CSofa) (00401073)   ; 调用沙发父类的构造函数  
  12. 0040120A    mov     dword ptr [ebp-4],0  
  13. 00401211    mov     ecx,dword ptr [ebp-10h]  
  14. 00401214    add     ecx,8           ; 将this指针调整到第二个虚表指针地址处  
  15. 00401217    call    @ILT+130(CBed::CBed) (00401087) ; 调用床父类的构造函数  
  16. 0040121C    mov     eax,dword ptr [ebp-10h] ; 获取第二个虚表指针地址  
  17.     ; 设置虚表指针  
  18. 0040121F    mov     dword ptr [eax],offset CSofaBed::'vftable' (00426198)  
  19. 00401225        mov     ecx,dword ptr [ebp-10h]     ; 获取对象的首地址  
  20.     ; 设置虚表指针  
  21. 00401228    mov     dword ptr [ecx+8],offset CSofaBed::'vftable' (0042501c)  
  22.     ; 部分代码分析略  
  23. 0040125D   ret 

在代码清单12-9的子类构造中,根据继承关系的顺序,首先调用了父类CSofa的构造函数。在调用另一个父类CBed时,并不是直接将对象的首地址作为this指针传递,而是向后调整了父类CSofa的大小,以调整后的地址值作为this指针,最后再调用父类CBed的构造函数。

由于有了两个父类,因此子类在继承时也将它们的虚表指针一起继承了过来,也就有了两个虚表指针。可见,在多重继承中,子类虚表指针的个数取决于所继承的父类的个数,有几个父类便会出现对应个数的虚表指针(虚基类除外,详见12.3节的讲解)。

这些虚表指针在将子类对象转换成父类指针时使用,每个虚表指针对应着一个父类,如代码清单12-10所示。

代码清单12-10 多重继承子类对象转换为父类指针

  1.     CSofaBed SofaBed;  
  2.     CSofa *pSofa = &SofaBed;  
  3. 0040F73C    lea     eax,[ebp-24h]           ; 直接将首地址转换为父类指针  
  4. 0040F73F    mov     dword ptr [ebp-28h],eax  
  5.     CBed *pBed = &SofaBed;  
  6. 0040F742    lea     ecx,[ebp-24h]  
  7. 0040F745    test    ecx,ecx     ; 检查对象首地址  
  8. 0040F747    je      main+51h (0040f751)  
  9. 0040F749        lea     edx,[ebp-1Ch]   ; 即lea edx, [ebp-24h+8h],调整为CBed的指针  
  10. 0040F74C    mov     dword ptr [ebp-30h],edx  
  11. 0040F74F    jmp     main+58h (0040f758)  
  12. 0040F751    mov dword ptr [ebp-30h],0  
  13. 0040F758    mov     eax,dword ptr [ebp-30h]  
  14. 0040F75B    mov     dword ptr [ebp-2Ch],eax ; 保存调整后的this指针 

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇12.2 多重继承(3) 下一篇12.2 多重继承(1)

评论

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