Re: [問題] 關於 enum 的 operator overloading
※ 引述《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
討論串 (同標題文章)