Re: [問題] 關於 enum 的 operator overloading

看板C_and_CPP作者 (putumaxally)時間11年前 (2014/05/25 11:57), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串3/4 (看更多)
※ 引述《LPH66 (1597463007)》之銘言: : ※ 引述《putumaxally (putumaxally)》之銘言: : : 問題(Question):overload operator 不能使用 pointer 當參數嗎? : : 上週在 C 語言的課堂上被老師問 pointer 跟 reference 的差別,我在 : : 網路上找資料的時候看到這段程式碼 : : enum day : : { : : Sunday, Monday, Tuesday, Wednesday, Thursady, Friday, Saturday : : }x; : : day& operator++(day& d) : : { : : d = (day)(d + 1); : : return d; : : } : : 不可以改成 day* operator++(day* d) 的形式 : : 只有當參數是 T, T& 才是 member operator 嗎,所以 T* 一定不會用在 : : operator overloading 嗎? : : 還有上面的例子是 prefix 的,那如果想要 postfix 該怎麼做呢 : : http://ppt.cc/Sa3Y 關於 pointer 跟 reference 的差別,我這樣描述對嗎? : 其實上面這個不是 member operator... : member operator 是在 class 當中直接寫 operator xxx : 例如 : class BigNumber : { : // ... : public: : BigNumber& operator ++ (); // member operator prefix ++ : BigNumber operator ++ (int); // member operator postfix ++ : }; : enum 由於無法宣告 member function 所以不會有 member operator : 因此只能用這個樣子寫在外面 : 同樣不得不寫在外面的狀況是 operator 的左邊是 primitive type : 或是 operator 的左邊那個 class 你動不到 : 例如我前面推文提到的 std::string 的例子 : 在 std::string 這個 class 裡有個 member operator == 是吃 const char * 的 : 概念上像是這樣: : class string : { : // ... : public: : bool operator == (const char *rhs) const; : }; : 這使得我們可以寫 someStringObject == "someCString" : 它就會去呼叫這個 member operator : 實際上它會視為 someStringObject.operator == ("someCString") 進行呼叫 : 但是 "someCString" == someStringObject 卻不一樣了 : 因為左邊是 primitive type 無法對它定義 member : 所以只好寫一個在 string 外面的 operator 它會長成像這樣: : bool operator == (const char *lhs, const string &rhs); : 這樣一來 "someCString" == someStringObject 這句話 : 就會被視為 operator == ("someCString", someObject) 來進行呼叫 : enum 的狀況由於無法定義 member function 只好用寫在外面的那種方式來定義 : 另一種要寫在外面的狀況的例子像是 : ostream& operator << (ostream& out, const BigNumber& num); : 由於 std::ostream 我們動不到 所以只好寫一個在外面的 operator : 這樣一來 cout << someBigNumber : 就會當成 operator << (cout, someBigNumber) 而呼叫到這個函式 : (寫在外面的 operator 其實還有一個 issue 是 namespace, 不過那跟本文就無關了) : --- : 至於 prefix postfix 的問題 : 在 member operator 的狀況是像上面我寫的 BigNumber 那樣子 : 同理可推, 寫在外面的也是以多一個 int 參數來表示 : 以 enum day 為例的話 postfix ++ 會寫成 : day operator ++ (day& d, int); : 這個 int 參數純粹只是用來解決 overload resolution 而已 : 實際上是不會用到的 : (編譯器實際上會丟一個 0 進去那個參數 不過那不重要) : 而通常 postfix ++ 是會回傳 value 而不是回傳 reference : 主要是因為要達成 postfix ++ 的語意會需要一個暫時物件 : 而你不能回傳一個暫時物件的 reference : 好在這種狀況大部份情形都能夠啟動 RVO 最佳化省去一次複製 : 因此這樣寫不會有什麼問題 : --- : 關於你的整理, 只有一個地方是錯的 : 陣列不是「傳址」 : 而是一個陣列變數除了某些特別的狀況之外 : 都會 decay 成一個指向其第一元素的指標 : (特別的狀況例如在 sizeof 裡面的時候) : 也就是說 那個例子裡 ptr = s; 這一行的 s 會 decay 成 &s[0] : 實際上它做的就是 ptr = &s[0]; : 這在這個變數傳進函式時也是一樣的 : 而 &s 雖然也會得到指向同一個位置的指標 : 但它的型態卻是不一樣的: : &s 的型態是 int(*)[5] -- 一個指向「長度為 5 的整數陣列」的指標 : 因此即使 &s 跟 &s[0] 指向的位置一模一樣 但 ptr = &s; 還是不合法 大致上都能夠理解 (汗 感謝大大讓我知道我對陣列的概念一直是錯的,之前在板上的文章看到 decay 都直接自動無視,一直堅持著陣列等同於指標(只是它永遠指向第一個元素) 我之前有寫過這種程式 http://pastebin.com/fv9DVKNW 這樣是合法的嗎(好像有看到置底的動畫說多維陣列不應該這樣用 reference parameter 的問題主要是看到這一篇文章 http://ppt.cc/R~t8 "However, this statement will not even compile because every overloaded operator function must either be a member of a class, or have a parameter of type T, T &, or T const &, where T is a class or enumeration type. So in this particular case, using a reference is the only way to do it." 對於他說的只能用 reference 當參數,一直無法知道為什麼,不過剛剛 google 了一下,看到類似的文章(貌似是同一個作者), "Every overloaded operator function must either be a member of a class, or have a parameter of type T, T &, or T const &, where T is a class or enumeration type. In other words, every overloaded operator must accept an argument of a class or enumeration type. A pointer, even to an object of class or enumeration type, doesn't count." 因為第一個參數必須讓 compiler 知道我是寫誰的運算子多載,而指標不算(被排擠? 所以 enum 的運算子多載第一個參數一定要用 enum type 或 reference 對吧。 硬要用指標的話就會跑出這種奇怪的程式碼 day operator+(day d1, day* d2); => d1 + &d2 PS.每次碰到C++的問題就會有一種感想,如果C是池塘,那C++就是大海,無窮無盡... 學校的老師(機械系)也不太敢教 C++,直接教 C# -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 175.180.68.25 ※ 文章網址: http://www.ptt.cc/bbs/C_and_CPP/M.1400990246.A.842.html
文章代碼(AID): #1JWMecX2 (C_and_CPP)
討論串 (同標題文章)
文章代碼(AID): #1JWMecX2 (C_and_CPP)