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

我们从实验中去总结问题

测试一: virtual 函数和non-virtual函数

01.#include <stdio.h>   

02.class A  

03.{  

04.public:  

05.      void function(){printf("Hello World");}  //无virtual关键字

06.  

07.};  

08.  

09.class B  

10.{  

11.public:  

12.      virtual void function(){printf("Hello World");}  

13.};  

14.  

15.int main( )  

16.{  

17.      A* p1 = NULL;  

18.      p1->function();  //正常运行

19.  

20.      B* p2 = NULL;  

21.      p2->function();  //crash,Why?

22.  Return 0;

23.};   

 

测试结果:18行正常,21行crash。

为什么18行正常,21行死机呢?

其原因是:

每一个非虚成员函数实际上都等同于一个普通的C函数,其中第一个参数为对象指针,即我们常说的this指针。例如:

上面的A的function函数实际等同于:A::Function()  ç==================èFunction(A*this);

与此不同,对每一个虚成员函数的调用都是通过虚函数表的虚指针vptr来进行调用的,如上面的p2->function一句将被编译器解释为:

                                       (* p2->vptr[1] )(p2)

很容易理解,虚函数的调用是动态决定的。也很容易理解,21行crash,18行正常。很显然,如果在A类的成员函数function里,有去使用成员变量,该函数同样会crash.


 

我们再来看看测试二:关于C++ static 成员函数

#include"stdio.h"

#include"stdafx.h"

#include<stdio.h>  

class A  

{  

  public:  

     void function(){ printf("Hello World");}  

      static A* instance();

     A();

       

};

static A *Test1 =NULL;

A::A()

{

     Test1 = this;

}

A* A::instance()

{

    return Test1;

}

int main( )  

{  

     A *StackObj = new A;

     delete StackObj;//Don’t set it to null intentionally….

     while(StackObj  && StackObj->instance() )

     {

          printf("Error--->%d.\n",StackObj);

     }

     return 0;

};   

 

Static函数没有this指针,可以认为他就是普通的c函数。

普通的c函数编译器都是通过name mangling技术,来对函数加以区分:

StackObj->instance()等同于:ZN1A8instanceEv()



 备注: 
①事实上编译器为了避免函数重载造成的重名情况,会对函数的名字进行处理,使之成为独一无二的名称。 (name mangling技术)
②将成员函数声明为static,可以使成员函数不经由this指针便可调用。 
③vptr表中,索引号0为类的type_info。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值