發現了一個空指針調用函數成功的例子,很奇怪就查了一下資料,如下:
舉個簡單的例子,假如有如下的一段代碼:
class MyClass
{
public:
int i;
void hello()
{
printf("hello\n");
}
void print()
{
printf("%d\n", i);
}
};
void main()
{
MyClass* pmy = NULL;
pmy->hello();
}
看上面的這段代碼,似乎很詭異。 用一個空指針調用成員函數,簡直是天大的錯誤,可以遺憾的是,卻是可行的,至少對於上面的這段程序來說,不會照成錯誤。
爲什麼?
其實,這並不是十分神祕的問題,假如你曾經使用過C封裝結構的話,對於這個問題,是十分好理解的。
在類初始化的時候,編譯器會將它的函數分配到類的外部,當然這也包括靜態成員函數,這樣的做法,主要是爲了節約內存,這也是爲什麼靜態函數可以在對象初始化之前運行的原因。
大家知道,每個對象,都有一個指向自己的this指針,這個指針的值,將會因爲對象的不同而不同,它的作用主要就是用來區分不同的對象,這樣你就可以根據它來訪問不同的對象的成員變量。
編譯器編譯後的成員函數的第一個參數是this指針,通過this指針引用數據成員及調用其它成員函數。
我們main函數中的hello函數並沒有使用類中的任何成員變量,所以,它也就不會用到this指針,此時的this指針是NULL。由於你調用的成員函數沒有使用到類的數據成員,所以即使傳入的this指針爲空,從而我們就可以沒有障礙的使用hello函數,然而相對的是,如果你在pmy->hello()之後接着調用pmy->print(),那麼將會報空指針錯誤,因爲這個函數試圖用this指針訪問成員變量i。