NULL转成类指针

转自:http://ycool.com/post/zqzzxd4

有一段代码简化如下:

 1 class CTest
 2 {
 3 public:
 4     void sayHello();
 5 
 6 private:
 7     char name[20];
 8 }
 9 
10 void CTest::sayHello(){
11     cout<<"Hello"<<endl;
12 }
13 
14 int main()
15 {
16     (CTest*)(NULL)->sayHello();
17     return 0;
18 }

 

        其中有一条如此语句: (CTest*)(NULL)->sayHello(),让我觉得比较困惑。怎么将NULL转换成一个类指针了呢。翻阅了资料得知,同时和同事交流了才了解,原来这样也是合法的。

        在C++中,一个类对象只有成员变量才有内存地址,成员函数是不占内存的。因为类不需要为每一个实例化出来的对象产生函数内存地址,而是让所有对象共用一个类的函数地址。要调用一个类的成员函数,只需要知道该类是什么类型就可以了。(CTest*)强制转换就是为了告诉编译器这个是CTest对象的指针,然后根据将该类的成员函数地址放进调用的地方。查看程序的汇编码会看到,在调用方法的时候是跳到一个函数地址,这个地址是在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();

        但是如果在调用的成员函数中用到了成员变量,那么就会产生异常。因为类为其每个对象都分配了一个成员变量用的内存空间,必须根据类指针去取。这里我们的类指针是指向NULL的,会产生非法内存访问。

posted @ 2014-10-28 10:41  felove  阅读(122)  评论(0)    收藏  举报