一叶知秋:“安全“的野指针、 static函数、成员函数、this 指针、gcc编译器、name mangling

  1. <span style="font-size:18px;">我们从实验中去总结问题  
  2.   
  3. 测试一: virtual 函数和non-virtual函数  
  4.   
  5. 01.#include <stdio.h>     
  6.   
  7. 02.class A    
  8.   
  9. 03.{    
  10.   
  11. 04.public:    
  12.   
  13. 05.      void function(){printf("Hello World");}  //无virtual关键字  
  14.   
  15. 06.    
  16.   
  17. 07.};    
  18.   
  19. 08.    
  20.   
  21. 09.class B    
  22.   
  23. 10.{    
  24.   
  25. 11.public:    
  26.   
  27. 12.      virtual void function(){printf("Hello World");}    
  28.   
  29. 13.};    
  30.   
  31. 14.    
  32.   
  33. 15.int main( )    
  34.   
  35. 16.{    
  36.   
  37. 17.      A* p1 = NULL;    
  38.   
  39. 18.      p1->function();  //正常运行  
  40.   
  41. 19.    
  42.   
  43. 20.      B* p2 = NULL;    
  44.   
  45. 21.      p2->function();  //crash,Why?  
  46.   
  47. 22.  Return 0;  
  48.   
  49. 23.};     
  50.   
  51.    
  52.   
  53. 测试结果:18行正常,21行crash。  
  54.   
  55. 为什么18行正常,21行死机呢?  
  56.   
  57. 其原因是:  
  58.   
  59. 每一个非虚成员函数实际上都等同于一个普通的C函数,其中第一个参数为对象指针,即我们常说的this指针。例如:  
  60.   
  61. 上面的A的function函数实际等同于:<span style="color:#ff0000;">A::Function()  ç==================èFunction(A*this);  
  62.   
  63. </span>与此不同,对每一个虚成员函数的调用都是通过虚函数表的虚指针vptr来进行调用的,如上面的p2->function一句将被编译器解释为:  
  64.   
  65.                                        (* p2->vptr[1] )(p2)  
  66.   
  67. 很容易理解,虚函数的调用是动态决定的。也很容易理解,21行crash,18行正常。很显然,如果在A类的成员函数function里,有去使用成员变量,该函数同样会crash.  
  68.   
  69.   
  70. <img alt="" src="https://img-my.csdn.net/uploads/201208/03/1343961187_7766.jpg">   
  71.   
  72. 我们再来看看测试二:关于C++ static 成员函数  
  73.   
  74. #include"stdio.h"  
  75.   
  76. #include"stdafx.h"  
  77.   
  78. #include<stdio.h>    
  79.   
  80. class A    
  81.   
  82. {    
  83.   
  84.   public:    
  85.   
  86.      void function(){ printf("Hello World");}    
  87.   
  88.       static A* instance();  
  89.   
  90.      A();  
  91.   
  92.          
  93.   
  94. };  
  95.   
  96. static A *Test1 =NULL;  
  97.   
  98. A::A()  
  99.   
  100. {  
  101.   
  102.      Test1 = this;  
  103.   
  104. }  
  105.   
  106. A* A::instance()  
  107.   
  108. {  
  109.   
  110.     return Test1;  
  111.   
  112. }  
  113.   
  114. int main( )    
  115.   
  116. {    
  117.   
  118.      A *StackObj = new A;  
  119.   
  120.      delete StackObj;//Don’t set it to null intentionally….  
  121.   
  122.      while(StackObj  && StackObj->instance() )  
  123.   
  124.      {  
  125.   
  126.           printf("Error--->%d.\n",StackObj);  
  127.   
  128.      }  
  129.   
  130.      return 0;  
  131.   
  132. };     
  133.   
  134.    
  135.   
  136. Static函数没有this指针,可以认为他就是普通的c函数。  
  137.   
  138. 普通的c函数编译器都是通过name mangling技术,来对函数加以区分:  
  139.   
  140. StackObj->instance()等同于:ZN1A8instanceEv()  
  141.   
  142.   
  143.   
  144.  备注:   
  145. ①事实上编译器为了避免函数重载造成的重名情况,会对函数的名字进行处理,使之成为独一无二的名称。 (name mangling技术)  
  146. ②将成员函数声明为static,可以使成员函数不经由this指针便可调用。   
  147. ③vptr表中,索引号0为类的type_info。   

http://blog.csdn.net/acs713/article/details/7825994

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值