看板 C_and_CPP 關於我們 聯絡資訊
最近看書提到運算子何時該是member function或non-member function. 因此整理一下給大家參考,也希望大家指導錯誤的地方 1.member function 和 non-member function的差異 A.non-member function 都是定義在class外面, 也被稱為global function. member function其實也有放在class的外面的機會, 通常會放在實作檔這邊,但是必須註明class的名稱. 反之non-member function不用在函式前面註明class的名字. 例如: test.h class myarray { int myfunction(int a, int b); } test.cpp //member function int myarray::myfunction(int a, int b) { ... } //non-member function int myfunction(int a, int b) B.兩者在main函式呼叫的方法不同 例如: int main() { int i; myarray a; //declare a myarray object i=myfunction(3,2); //non-member function i=a.myfunction(3,2); //member function } 2.理解兩者在運算子上的使用差異 以下面所舉二元運算子為例, <lhs> <op> <rhs> A.如果是member function來 overload, 左邊的 operand 一定是所屬的物件, 右邊的 operand 就是傳進來的參數, 編譯器實際上呼叫方式是lhs.operator<op>(rhs) B.如果是non-member function來overload, 要註明左邊跟右邊的運算元類型. 它的寫法是T operator<op>(T1 lhs, T2 rhs), T是傳回的類型,可以跟參數類型一樣. 編譯器實際上呼叫方式是operator<op>(lhs, rhs) 3.使用準則(用來決定運算子該是member function或non-member function) A.一元運算子是members B.= [] ()和->必須是members C.assignment版的運算子(+=,-+等)必須是members D.其他所有二元運算子都應該是nonmembers 參考資料 1.http://www.cs.uregina.ca/Links/class-info/210/Overloading/membervsregular.html 2.http://www.programmer-club.com.tw/ShowSameTitleN/c/31905.html 3.Exceptional C++ 國際中文版: 47個工程難題`編程疑問`及其解決方法/Herb Sutter原著;侯捷 譯 -台北市:普林帝斯霍爾,2000[民89] -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 61.220.204.217
shadow0326:我對3-D有疑惑, 可以請問"應該"的理由嗎? 11/16 16:13
ex: 當operator +為member function時 Object obj; double x; double y; x=obj+y;->x=obj.operator+(y)//這是ok 但是x=y+obj;->x=y.operator+(obj);//這是無法辦到的 上一行的結果是不自然的, 你不能要求使用者永遠只能用x=obj+y;去撰寫程式. 實際上作者也知道implict的問題,因此它用多載來解決. 至於shadow0326遲遲無法完全接這理由, 還有一個原因.我沒有拿<<和>>當例子.(><因為我無法理解書中的解釋,只能請其他人舉例) ps: 拍謝,引用tropical72為例子
legnaleurc:因為 members => 看得到 private => 高耦合吧 11/16 16:37
tropical72:Object obj;double x,y; x=obj+y; x=obj.operator+(y) 11/16 16:51
tropical72:此使 memmber 即可, 考慮 x=y+obj; 11/16 16:51
tropical72:( x=y.operator+(obj); 錯誤), 需用 global overload 11/16 16:51
tropical72:為考量x=y+obj/x=obj+y 均可正常執行,故建議用 11/16 16:51
tropical72:global overload operator. 11/16 16:51
Ag2S:想問一下,private data就只好用friend解嗎?這樣會比較好? 11/16 16:54
tropical72:試想一下如果 class string 要支援 strlen() 的話怎做? 11/16 17:10
tropical72:別把 friend 視作會破壞oo,擅用它會使得oo更好. 11/16 17:11
shadow0326:唔, 要滿足交換率的前提應該是能掌握好implict轉換的結 11/16 17:19
shadow0326:果吧, 反過來說, 如果implict轉換會造成非預期的結果, 11/16 17:20
shadow0326:non-member似乎反而會造成麻煩? 11/16 17:20
angleevil:其實tropical72的解釋比我好,你問這個問題時,我還真不知 11/16 17:20
angleevil:到如何回答.基本上non-member也可以用多載來解決 11/16 17:22
angleevil:ex:operator+(const complex& lhs,const double & rhs) 11/16 17:22
angleevil:operator+(const double& lhs,const const & rhs) 11/16 17:23
shadow0326:當然也可以寫兩個多載來避免implict, 不過我是覺得不一 11/16 17:23
shadow0326:有必要為了滿足交換率而做到這種地步... 11/16 17:23
shadow0326:更正: 不一定 11/16 17:24
angleevil:但是當你把相加的結果assign時,就必須是non-member 11/16 17:26
shadow0326:結果的assign是由operator的回傳型態決定的吧? 11/16 17:27
angleevil:不對喔,你要先看看2A.它實際上是怎樣呼叫的 11/16 17:28
angleevil:它實際上是用物件(lhs)呼叫operator+.然後用rhs當參數 11/16 17:30
shadow0326:那基本上還是是否滿足交換率的問題吧, 和結果的關係是? 11/16 17:30
angleevil:你可以參考tropical72的解釋.y.operator+(obj);<-- 11/16 17:34
angleevil:而且2A說過了左邊的運算元一定是所屬的物件. 11/16 17:36
tropical72:回文討論吧,推文裡的東西版上都還沒有,可以討論很久. 11/16 17:39
shadow0326:我覺得有點鬼打牆了 XD 我知道operator的呼叫方式, 也 11/16 17:42
shadow0326:理解建議non-memeber的理由 (後者要感謝t大和a大) 11/16 17:42
shadow0326:我只是想說non-member可能付出的代價(implict的問題) 11/16 17:43
shadow0326:以及是否有必要為了滿足交換率特地寫兩條實作幾乎相同 11/16 17:44
tropical72:我能理解 shadow0326 考量在哪,但那問題在複載二元運算 11/16 17:44
shadow0326:的overload. (當然我支持有些時候non-member真的較好) 11/16 17:45
tropical72:子時就一定要考量,甚至必要時也會提供 static_cast<T> 11/16 17:45
tropical72:之複載. 11/16 17:45
angleevil:shadow0326,我引用tropical72的例子來解釋理由,看看還有 11/16 17:48
angleevil:疑問嗎? 也希望其他人幫忙多找問題和回答 11/16 19:28
※ 編輯: angleevil 來自: 61.220.204.217 (11/17 08:25) ※ 編輯: angleevil 來自: 61.220.204.217 (11/17 11:35)
cgcheng:幾乎同樣的實作?func(lhs,rhs){ func(rhs,lhs) } 11/18 04:47
cgcheng:看這樣會不會好點,加個兩行滿足需求 11/18 04:48
cgcheng:implict的問題是比較麻煩點,不過根據use case好像可以避開 11/18 04:52
angleevil:樓上可以講解更清楚嗎?直接給func(lhs,rhs)不知是member 11/18 07:14
angleevil:or nonmember case? 還是說用一個member function的功能 11/18 07:15
angleevil:取代operatior overloading? ><而且我不太知道use case 11/18 07:19
angleevil:的意思是什麼? 麻煩大家解惑一下 11/18 07:19
shadow0326:我想c大的意思是例如 operator + (l,r){return r+l} 11/18 10:18