當類的指針被賦值爲NULL時,類的哪些成員還可以被該指針調用

該問題源自於一道面試題,題目如下所示:

看如下代碼,請問能不能編譯通過?如果能編譯通過能不能運行成功?並說明原因

class test
{
public:
	int fun(){return 1;};
};

int main ()
{
	test *t = NULL;
	int res = t->fun();

	return 0;
}

好的,我們現在先來分析這道題目,初一看,該代碼應該可以編譯通過,但是運行肯定不會過,因爲t是NULL了嘛,怎麼還能再調用成員函數呢。

現在我們把這段代碼貼到VS裏,編譯,運行,斷點,發現沒報錯,一切正常,res值爲1...

好神奇!

通過查找一些資料,我發現:

因爲函數在類裏面是獨立於類存在的,而且不佔用類的空間,在程序編譯的時候就已經把函數的地址分配好了,因此,只要有這麼一個對象,不管他指向NULL還是非NULL,都是可以調用該函數的,也不會出錯。

那好,既然這樣,我們再來看下面這段代碼:

class test
{
public:
	test() {m_num = 0;};

	int fun1() {return 1;};
	static int fun2() {return 2;};
	virtual int fun3() {return 3;};
	int fun4() { return m_num;};

private:
	int m_num;
};

int main ()
{
	test *t = NULL;
	int res1 = t->fun1();
	int res2 = t->fun2();
	int res3 = t->fun3();
	int res4 = t->fun4();

	return 0;
}
放到編譯器中,fun1,fun2可以正常運行,fun3,fun4運行出錯,這又是爲什麼呢?

fun1上面已經分析過了,可以運行沒問題;

fun2是靜態函數,本身就不屬於類,所以跟類的指針沒有關係,可以運行,也沒有問題;

fun3是虛函數,而虛函數是通過虛函數表來實現的,而虛函數表是存在於對象中的,對象爲NULL了,自然就無法訪問了;

fun4是調用了類的成員變量,而成員變量也同樣是存在於類的對象中的,爲NULL的的對象沒有了成員變量的存儲空間,也無法訪問。

以上是對該問題相對錶層的分析,要想進一步瞭解該問題,建議看一下關於“__thiscall”的解釋,可以參考如下博文:

http://blog.csdn.net/yc_8301/article/details/1814744

我也會在後續的文章中專門對該問題做一個分析,敬請關注。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章