大一程設-下
東華大學
東華大學資管系
基本程式概念
資管經驗分享
多載運算子的核心概念 : 自己定義運算子的行為
簡化程式複雜性,增加閱讀性。
以使用者的角度,他不會知道背後實作的細節。(這句話是重點!!)
Orange
應該都記得運算子是什麼,
+-*/
、++、--
、>>、<<
、==、=
之類的很多運算子。
以四則運算的 +
號為例,如果執行 5 + 10,照常會把兩個數字做相加,而今天自定義 +
號的意思就是,讓他執行我們自己設定的行為。比方說 5 + 10 透過我們自定義之後,會執行 5 * 2 + 10 * 2。這邊就是說每個數字先 * 2 再相加這件事是我們自己定義的。
還是不太懂吧,我們繼續往下,但這樣的概念你們可以先有。
不失一般性,我還是想先讓大家知道為甚麼要做這件事。
tip: 面對這樣的題目或敘述,請先確定需求!
如果今天沒有 operator overloading 我們可能會實作出下面的類別。
範例很長,下面會分段說明。
接下來我會以開發者的角度解釋為甚麼要使用 operator overloading
可以看看上面的例子,為了輸入名字、輸入成績、算平均、算總和、取得成績,我們實作了非常多的 member function,你可以發現為了一件小事情,為了劃分功能我們可能會拆成 function 出去,這件事情本身沒有問題,邏輯很正確。也確實得到了我們的效果。
但這樣的問題是,一個小功能我們就需要一個 function,隨著功能越來越多,我們會宣告更多的函式,對於開發而言,其實有點沒有效率。
而你也可以看到上例需要非常多的,輸入、取值的動作,這個時候如果自定義運算子來執行我們的行為,我們可以簡化非常多的程式。
為了搭配老師用的教科書,我們先說明結合 friend 的運算子多載。
此處不再說明何為 friend,忘記請回去看前面的筆記。
了解多載運算子的參數傳遞之前,我們在每次要多載的時候,要先知道我們要多載的運算子是幾元的運算子。比方說多載 +-*/
是二元運算子,>> <<
是二元運算子,但是 +-
,也能夠當作一元運算子來使用。沒有多載的時候他們是表達正負號。
所以根據你要多載的運算子是幾元運算子,就會需要幾個參數。
而運算子的運作方式則不會改變,多載二元運算子的加號一定要寫 變數1 + 變數2
。依此類推。
而根據你的參數的型態,你必須用相對應型態的變數來使用多載的運算子,以下舉例。
可以看到上面這段程式,我們實作了多載 +
運算子,其有兩個參數,都是 student 物件,所以今天若是要呼叫自定義的多載運算子,必須確實使用兩個 student 物件來呼叫他。
而上面這段多載運算子是在執行把兩個當作參數傳入的學生的成績做相加。
到這邊都理解的話,我們直接看下方的大例子,直接修改上方的例子。
範例很長,下面會分段說明。
可以上下比對兩個例子,main function 的簡潔度差非常多。類別本身的定義也簡潔很多。
但你可能會說,實際比較下來不就是把 function 的內容全部都實作到 operator overloading 裡嗎? 看起來其實也沒有比較方便。
直觀理解下來是這樣沒有錯,但其實實作 operator overloading 自定義運算子之後,我們能夠結合 friend 憑藉參數來取用私有屬性,而且可以自定義我們想要的行為,如果今天仍是使用成員函式,我們的行為會被綁定,因為 function 要在類別內先被定義好。
那你會說,我就想要宣告一堆 function 在 class 裡阿。
沒有不行,完全可以
Orange
這邊不考慮抽象方法之類的內容。
歡迎自行上網學習!
Orange
所以究竟要不要使用 operator overloading 是看需求的,他確實提供了一個額外的選項讓我們實作程式,讓我們有更多工具把玩程式。學起來有利無弊。
相信 istream
與 ostream
對第一次見到的你們肯定不陌生(?。
還記得在第六章有 ifstream
跟 ofstream
兩個類別,全名 input file stream/ output file stream
,負責檔案讀入與寫出串流。
而 istream/ostream
則是負責使用者輸入與輸出的串流的類別。
這裡我們自定義了 >>
運算子,而第一個參數必須要是輸入串流物件,第二個參數是一個學生物件,最後會回傳一個輸入串流物件,所以為了滿足行為,可以看上方第 13 行,
cin 滿足第一個參數,s1 滿足第二個參數,根據我們自定義了 >>
的行為,參數符合呼叫的規定,所以這邊的 cin >> s1
會執行我們自定義的 operator overloading。
第 14 行的自定義 <<
也同理,可以自己理解一下。
上方例子的第五行與第六行做了連續的輸入動作,因為參數符合自定義運算子的呼叫,所以執行 operator overloading。
還記得運算子的優先權,>>、<<
這兩個運算子是左結合,所以左邊優先,實際運作起來會像下面這樣
而每一次輸入都會回傳一個讀入串流物件(根據我們上面自定義的運算子),所以 cin >> s1
執行完之後會把讀入串流 cin 回傳回來,再執行 cin >> s2
,依此類推。
.
::
今天運算子多載若要宣告成 member function 也是完全沒問題的,但這樣要呼叫時就必須要由一個實體化的物件親自呼叫來觸發。
可以看底下 Reference 的第一篇。
上面有關 friend 的都看懂了的話沒 friend 的你一定也能夠心領神會了
我有空會再回過頭來補
Orange
究竟 operator overloading 要不要使其為 friend function,要依照你的需求,實作的 function 能不能存取私有屬性或方法來決定,所以沒有一定。