事情缘起是因为上班途中刷到了有个微博,那人说答对这个问题的请发简历。
看了就是关于指向C++类的指针的知识,原代码类似下面这样:
class NullPointCall
{
public:
void display()
{
cout << "It's nice!" << endl;
};
private:
int m_num;
};
问题类似于:
NullPointCall *pNull = NULL;
pNull->display();
// 求问结果是什么
// A、coredump
// B、显示It is nice!
// C、...(我忘了啥答案了 囧...)
// D、其他错误
然后参考了网上的博客,这有关this指针。
class NullPointCall
{
public:
static void Test1()
{
cout << m_staticInt << endl;
};
void Test2()
{
cout << "It is nice!" << endl;
};
void Test3(int inputNum)
{
cout << inputNum << endl;
};
void Test4()
{
cout << m_variable << endl;
};
private:
static int m_staticInt ;
int m_variable ;
};
int NullPointCall::m_staticInt = -10;
然后测试如下:
NullPointCall *pNull = NULL;
pNull->Test1();
pNull->Test2();
pNull->Test3(2);
pNull->Test4();
然后输出为:
-10
It is nice!
2
Test4()失败,内存访问冲突
对于类成员函数而言,并不是一个对象对应一个单独的成员函数体,而是此类的所有对象共用这个成员函数体。 当程序被编译之后,此成员函数地址即已确定。而成员函数之所以能把属于此类的各个对象的数据区别开, 就是靠这个this指针。函数体内所有对类数据成员的访问, 都会被转化为this->数据成员的方式。
当在类的非静态成员函数中访问类的非静态成员的时候,编译器会自动将对象本身的地址作为一个隐含参数传递给函数。即使你没有写上this指针,编译器在编译的时候也是加上this的。
对于上面的例子来说,this的值也就是pNull的值。也就是说this的值为NULL。
Test1()是静态函数,编译器不会给它传递this指针,所以call 1那行代码可以正确调用(这里相当于CNullPointCall::Test1())。
对于Test2()和Test3()两个成员函数,虽然编译器会给这两个函数传递this指针,但是它们并没有通过this指针来访问类的成员变量,所以Test2()和Test3()两行代码可以正确调用。
而对于成员函数Test4()要访问类的成员变量,因此要使用this指针:
void NullPointCall::Test4(NullPointCall *this)
{
cout << this->m_variable << endl;
}
相当于:
void NullPointCall::Test4(pNULL)
{
cout << this->m_variable << endl;
}
这个时候发现this指针的值为NULL,就会造成程序的崩溃。