1. 程式人生 > >當類的指標被賦值為NULL時,類的哪些成員還可以被該指標呼叫

當類的指標被賦值為NULL時,類的哪些成員還可以被該指標呼叫

轉自:https://blog.csdn.net/xiaoluer/article/details/53337292

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

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

 

 
  1. class test

  2. {

  3. public:

  4. int fun(){return 1;};

  5. };

  6.  
  7. int main ()

  8. {

  9. test *t = NULL;

  10. int res = t->fun();

  11.  
  12. return 0;

  13. }


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

現在我們把這段程式碼貼到VS裡,編譯,執行,斷點,發現沒報錯,一切正常,res值為1...

好神奇!

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

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

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

 

 
  1. class test

  2. {

  3. public:

  4. test() {m_num = 0;};

  5.  
  6. int fun1() {return 1;};

  7. static int fun2() {return 2;};

  8. virtual int fun3() {return 3;};

  9. int fun4() { return m_num;};

  10.  
  11. private:

  12. int m_num;

  13. };

  14.  
  15. int main ()

  16. {

  17. test *t = NULL;

  18. int res1 = t->fun1();

  19. int res2 = t->fun2();

  20. int res3 = t->fun3();

  21. int res4 = t->fun4();

  22.  
  23. return 0;

  24. }

放到編譯器中,fun1,fun2可以正常執行,fun3,fun4執行出錯,這又是為什麼呢?

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

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

fun3是虛擬函式,而虛擬函式是通過虛擬函式表來實現的,而虛擬函式表是存在於物件中的,物件為NULL了,自然就無法訪問了;

fun4是呼叫了類的成員變數,而成員變數也同樣是存在於類的物件中的,為NULL的的物件沒有了成員變數的儲存空間,也無法訪問。

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

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

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