爲什麼可以不創建對象就調用類的成員函數?

http://bbs.51cto.com/thread-848191-1.html








以下代碼是可以正常運行的
class Base 

public: 
    void print() 
    { 
        printf("print :Base!\n"); 
    } 
}; 
int main()
{
    Base* b=NULL; 
    b->print(); 
   return 0;
}
沒有創建類對象,卻可以調用類的不包含成員變量的成員函數。學校論壇上有人的解釋是“編譯器實際上是把所有的類成員函數改名(name mangling)並加上一個本類的this指針,使其非成員化。所以,在程序開始運行時,所有成員函數代碼的地址已經確定,所有類對象共享, 而不像成員變量(非static)必須在實例化後才分配內存並且每個實例都擁有一份。”
但是我疑惑的是,爲什麼C++作爲面嚮對象語言可以不創建對象就訪問一個屬於類的方法?這樣做有什麼好處?一個類方法雖然沒有使用到類屬性,但也應該是類行爲,應該是這類對象才能夠具備的,爲什麼可以隨便調用?
至少在Java裏面
Base b=null; 
    b->print(); //error,need Base b=new Base(); 
這樣是錯誤的,必須創建對象。

最佳答案



 

1. 樓主求知精神值得學習
2. 給你解釋的人說的基本上是正確的。
成員函數編譯以後就是普通的函數,
比如Base的Print被改名爲void Print_Base_xxxxx(Base* pBase);
那b->Print被轉爲Print_Base_xxxxx(NULL);

其實更激烈點的方式,比如Derived繼承於Base,它實現了Print這個函數。
你在main裏面調用
Derived* pDerived = NULL;
pDerived->Print;

再做一個假設,你想crack這個編譯後的可執行程序。

你找個反彙編工具,看到函數調用call ptr[derived_print_xxx]類似這樣一條語句,把它改爲call ptr[base_print_xxx].再運行程序,你會發現調用的是Base的Print。

所以說成員函數和普通的非成員函數沒有本質的區別(起碼編譯以後是這樣),調用的方法也是一樣的。
3. 編譯器實現問題樓主不必深究。如果有興趣你可以去windws mobile資源區看看ansi c++ standard,看看裏面有沒有對這個的實現做出具體的規定。如果c++ standard沒有具體規定,那麼不同的c++廠商怎麼實現自己定。





 

多謝樓上。。。不過暫時還沒有精力這麼深入的研究,不過我會看的





 

嗯,多謝V哥,代碼的實現問題基本理解,“所以說成員函數和普通的非成員函數沒有本質的區別(起碼編譯以後是這樣),調用的方法也是一樣的。”
我只是想問,爲什麼C++要設計成這樣,我覺得從面向對象概念上來講,成員函數就應該和普通函數區分開來,一個類方法雖然沒有使用到類屬性,但也應該是類行爲,應該是這類對象才能夠具備的,爲什麼可以隨便調用?
C++這麼做有什麼好處?
也許我鑽牛角尖了,C++就是這麼設計的,我也沒啥辦法。。。





 

成員函數與成員變量不同。成員函數,不需要反覆的去聲明、定義,可以節省好多空間。成員變量不能這麼做,那是因爲每個對象有所不同,當然,靜態成員例外。




 
發佈了11 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章