设为首页 加入收藏

TOP

12.4 菱形继承(4)
2013-10-07 14:30:50 来源: 作者: 【 】 浏览:58
Tags:12.4 菱形 继承

12.4 菱形继承(4)

代码清单12-15展示了子类CSofaBed的构造过程,它的特别之处是在调用时要传入一个参数。这个参数是一个标志信息。构造过程中要先构造父类,然后构造自己。CSofaBed的两个父类有一个共同的父类,如果没有构造标记,它们共同的父类将会被构造两次,因此需要使用构造标记来防止重复构造的问题,构造顺序如下:

CFurniture

CSofa(根据标记跳过CFurniture构造)

CBed(根据标记跳过CFurniture构造)

CSofaBed自身

CSofaBed也使用了构造标记,当CSofaBed也是父类时,这个标记将产生作用,跳过所有父类的构造,只构造自身。当标记为1时,则构造父类;当标记为0时,则跳过构造函数。构造时可以使用标记来防止重复构造,同样也不能出现重复析构的错误,那么这又如何实现呢?我们来看一下代码清单12-16。

代码清单12-16 菱形结构的子类析构

  1. // CSofaBed 调用析构代理函数,因为是编译器自动添加的,所以无源码对照  
  2. CSofaBed::'vbase destructor':  
  3. ; 部分代码分析略  
  4. 00401AE9   pop      ecx  
  5. 00401AEA    mov dword ptr [ebp-4],ecx  
  6. 00401AED    mov     ecx,dword ptr [ebp-4]  
  7. 00401AF0    add     ecx,20h  
  8.     ; 调用CSofaBed的析构函数  
  9. 00401AF3    call    @ILT+90(CSofaBed::~CSofaBed) (0040105f)  
  10. 00401AF8    mov     ecx,dword ptr [ebp-4]  
  11. 00401AFB    add     ecx,20h  
  12.     ; 调用祖父类的析构函数  
  13. 00401AFE    call        @ILT+60(CFurniture::~CFurniture) (00401041)  
  14. ; CSofaBed::~CSofaBed实现  
  15.     virtual ~CSofaBed(){  
  16. ; 部分代码分析略  
  17. 00401B5E    pop     ecx             ; 还原this指针  
  18. 00401B5F    mov     dword ptr [ebp-10h],ecx ; 调整this指针  
  19. 00401B62    mov     eax,dword ptr [ebp-10h]  
  20.     ; 设置自身虚表  
  21. 00401B65    mov     dword ptr [eax-20h],offset CSofaBed::'vftable' (00425034)  
  22. 00401B6C    mov     ecx,dword ptr [ebp-10h]  
  23.     ; 设置自身虚表  
  24. 00401B6F    mov     dword ptr [ecx-14h],offset CSofaBed::'vftable' (00425028)  
  25. 00401B76    mov     edx,dword ptr [ebp-10h]  
  26. 00401B79    mov     eax,dword ptr [edx-1Ch]  
  27. 00401B7C    mov     ecx,dword ptr [eax+4]  
  28. 00401B7F    mov     edx,dword ptr [ebp-10h]  
  29.     ; 设置自身虚表。到此为止,3个虚表指针设置完毕,执行析构函数内的代码  
  30. 00401B82    mov     dword ptr [edx+ecx-1Ch],offset CSofaBed::'vftable' (0042501c)  
  31. 00401B8A    mov     dword ptr [ebp-4],0  
  32. printf("virtual ~CSofaBed()\r\n");  
  33. }  
  34. 00401B9E   mov      eax,dword ptr [ebp-10h]  
  35. 00401BA1   sub      eax,20h     ; 获取this指针  
  36. 00401BA4   test     eax,eax     ; 检查this指针  
  37. 00401BA6   je       CSofaBed::~CSofaBed+83h (00401bb3)  
  38. 00401BA8   mov      ecx,dword ptr [ebp-10h]  
  39. 00401BAB   sub      ecx,14h  
  40. 00401BAE   mov      dword ptr [ebp-14h],ecx  
  41. 00401BB1   jmp      CSofaBed::~CSofaBed+8Ah (00401bba)  
  42. 00401BB3   mov  dword ptr [ebp-14h],0  
  43. 00401BBA   mov  ecx,dword ptr [ebp-14h]  
  44. 00401BBD   add  ecx,10h     ; 调整this指针  
  45. 00401BC0   call     @ILT+75(CBed::~CBed) (00401050) ; 调用父类析构函数  
  46. 00401BC5   mov      dword ptr [ebp-4],0FFFFFFFFh  
  47. 00401BCC    mov     ecx,dword ptr [ebp-10h]  
  48. 00401BCF    sub     ecx,14h     ; 调整this指针  
  49. 00401BD2    call    @ILT+125(CSofa::~CSofa) (00401082)  ; 调用父类析构函数  
  50.     ; 部分代码分析略  
  51. 00401BF1        ret 

根据对代码清单12-16的分析可知,菱形结构中子类的析构函数执行流程并没有像构造函数那样使用标记来防止重复析构,而是将祖父类放在最后调用。先依次执行两个父类CBed和CSofa的析构函数,然后执行祖父类的析构函数。Release版下的原理也是如此,这里就不再重复分析了。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇12.1 识别类和类之间的关系(12) 下一篇12.4 菱形继承(3)

评论

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