类指针与NULL

给定如下代码,给出输出结果

输出结果为:

1)Hi
2)Hi                                                  //这里p=NULL后还能正确调用p->hi()并输出Hi
3)Hi 1

4)然后再输出i->hi()的时候程序挂掉了~

在讨论为什么第二个p->hi()能有结果而第二个i->hi()程序奔溃之前请再看下面一个例子

注意在main函数里面出现了(CTest*)(NULL)->sayHello()但是依然能正确输出结果。

综合上述两个例子,分析如下(下述内容引自http://shokey520.ycool.com/post.2965150.html):

 

在C++中,一个类对象只有成员变量才有内存地址,成员函数是不占内存的。因为类不需要为每一个实例化出来的对象产生函数内存地址,而是让所有对象共用一个类的函数地址。要调用一个类的成员函数,只需要知道该类是什么类型就可以了CTest*)强制转换就是为了告诉编译器这个是CTest对象的指针,然后根据将该类的成员函数地址放进调用的地方。同理,p=NULL后但是p仍然为Person类型,所以可以调用p->hi()。查看程序的汇编码会看到,在调用方法的时候是跳到一个函数地址,这个地址是在main函数之前的。
((CTest*)(0))->sayHello();
004024A8 xor ecx,ecx
004024AA call @ILT+55(CTest::sayHello) (0040103c)

@ILT+55(?sayHello@CTest@@QAEXXZ):
0040103C jmp CTest::sayHello (00401170)

void CTest::sayHello()
{
00401170 push ebp
00401171 mov ebp,esp
……

所以上述代码是可以正确运行的,这样做的目的是为了不产生一个局部对象。常见做法可能是
CTest a;
a.sayHello();

但是如果在调用的成员函数中用到了成员变量,那么就会产生异常(就像i->hi()一样,因为Intern类的hi()成员函数里面有一个成员变量i,因此当i=NULL的时候再调用i->hi()则发生异常)因为类为其每个对象都分配了一个成员变量用的内存空间,必须根据类指针去取。这里我们的类指针是指向NULL的,会产生非法内存访问。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值