C++中,空指針是不可以使用的,而後空對象指針有時候卻可以調用成員函數。
下面定義一個簡單的類:函數
class TestCls { public: static void Test_Fun1(){ cout<<"Test_Fun1"<<endl; } void Test_Fun2(){ cout<<"Test_Fun2"<<endl; } void Test_Fun3(){ cout<<m_num<<endl; } virtual void Test_Fun4{ cout<<"Test_Fun4"<<endl; } public: int m_num; }; int main() { TestCls* pTestCls = NULL; pTestCls->Test_Fun1(); //OK, print Test_Fun1 pTestCls->Test_Fun2(); //OK, print Test_Fun2 pTestCls->Test_Fun3(); //Error pTestCls->Test_Fun4(); //Error }
空指針對Test_Fun1和 Test_Fun2的調用正常,對Test_Fun3和Test_Fun4的調用會出錯。下面具體 分析一下緣由:
類的成員函數並不與具體對象綁定,全部的對象共用同一份成員函數體,當程序被編譯後,成員函數的地址即已肯定,這份共有的成員函數體之因此可以把不一樣對象的數據區分開來,靠的是隱式傳遞給成員函數的this指針,成員函數中對成員變量的訪問都是轉化成"this->數據成員"的方式。所以,從這一角度說,成員函數與普通函數同樣,只是多了一個隱式參數,即指向對象的this指針。而類的靜態成員函數只能訪問靜態成員變量,不能訪問非靜態成員變量,因此靜態成員函數不須要指向對象的this指針做爲隱式參數。
有了上面的分析,就能夠解釋爲何空對象指針對Test_Fun1, Test_Fun2的調用成功,對Test_Fun3 的調用不成功:
Test_Fun1是靜態成員函數,不須要this指針,因此即便pTestCls是空指針,也不影響對Test_Fun1的正常調用。
Test_Fun2雖然須要傳遞隱式指針,可是函數體中並無使用到這個隱式指針,也就是說沒有經過 這個隱式指針去使用非靜態的成員變量,因此pTestCls爲空也不影響對Test_Fun2的正常調用。
Test_Fun3就不同了,由於函數中使用到了非靜態的成員變量,對num的調用被轉化成 this->num,也就是pTestCls->num,而pTestCls是空指針,所以pTestCls->num非法,對Test_Fun3的調用出錯。
Test_Fun4中並無使用非靜態成員變量,爲何調用也會出錯呢,緣由在於Test_Fun4是虛函數, 有虛函數的類會有一個成員變量,即虛表指針,當調用虛函數時,會使用虛表指針,對虛表指針的使用也是經過隱式指針使用的,所以對Test_Fun4的調用也就會出錯了。this