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的,会产生非法内存访问。
浙公网安备 33010602011771号