面试中会有这样的题目,实际项目也有人遭过!是什么呢,就是类对象被释放后,还可以访问class成员函数,因为编译过了,运行中没有check null就会直接调用,下面我们可以看看奇葩的两种用法。
#includeclass test{ public: void print(){ printf("%s\n",__FUNCTION__ ); } #includeclass test{ public: test():m_Val(0){ } void print(){ printf("%s\n",__FUNCTION__ ); } void funusemem(){ printf("%s\n",__FUNCTION__ ); printf("m_Val is :%d\n", m_Val); } private: int m_Val; }; int main(){ test* p = new test; delete p; p = NULL; int* m = new int; ((test*)m)->funusemem(); p->funusemem(); return 0; }
他们都成功调用了print函数.
那再让我们看看另外一种会挂掉的用法:
#includeclass test{ public: test():m_Val(0){ } virtual void print(){ printf("%s\n",__FUNCTION__ ); } void funusemem(){ printf("%s\n",__FUNCTION__ ); printf("m_Val is :%d\n", m_Val); } private: int m_Val; }; int main(){ test* p = new test; delete p; p = NULL; int* m = new int(1998); ((test*)m)->funusemem(); p->funusemem(); return 0; }
第一个仍然不会挂,第二个会挂,特么很诡异吧,第二个挂的原因是this指针为NULL会segmentation fault.
第一个不仅不会错误,而且输出了1998,哈哈,这就是C++ class的调用机制,你看到木有,因为这里没有virtual table,所以第一个mem直接是*(int*)this,所以这里不会有问题,如果有虚函数肯定就会错!(这个已测试)
所以C++坑还是比较多的,可以多踩踩,特么才知道oh shit!