推 LPH66: 這兩種都是同一種狀況: operator 左邊的東西動不到的時候 05/23 23:25
→ LPH66: 其他狀況寫 member 比較好管理也容易知道這些是一起的 05/23 23:27
→ LPH66: 你的 Complex * double 其實可以寫成 Complex 的 member 05/23 23:27
→ LPH66: 參數放 double 即可; 需要外面的是 double * Complex 05/23 23:28
→ LPH66: 不過這種狀況其實一般不會寫 operator 而是用型態轉換 ctor 05/23 23:28
→ LPH66: 當有 Complex::Complex(double) 及 Complex * Complex 時 05/23 23:29
→ LPH66: 編譯輯會把它用前者變成 Complex 再呼叫後者 05/23 23:29
> -------------------------------------------------------------------------- <
作者: Feis (坐吃山空) 看板: C_and_CPP
標題: Re: [問題] 關於運算子重載(operator overloading)
時間: Sun May 24 23:34:03 2015
※ 引述《wtchen (沒有存在感的人)》之銘言:
: 問題(Question):
: 目前正在寫一個可以進行加減乘除的大數class。
: 有一個關於operator overloading的問題:
: 據我所知可以使用method(寫在class裏面)或function(class外面)
: 請問一般情況下使用method還是function好呢?
: 我想要overload的operator包括
: +, -, *, /, +=, -/, *=, /=, %
: 目前我唯二知道需要用function解決的有兩種情況:
: - operator 作用於 class 跟另一種 class
: ex: Complex a; double b; Complex c = a * b;
: - 需要用到cout <<
: ex: Complex a(1,1); cout << a << endl;
: 謝謝。
就 C++ 而言,在成員或非成員函式取捨時我的想法大概是這樣的順序:
1. 語法限制: 有些情況下你根本沒得選
情況一: operator=, operator[], operator() 和 operator-> 在標準規定是不能用
非成員函式多載。此時只能用成員函式。
情況二: 當你為二元運算子時,如果左運算元的類別定義無法更改。例如你提到
cout << a; 。此時只能用非成員函式。
情況三: 當你為一元運算子時,如果運算元為 enum 型態,此時只能用非成員函式。
2. 安全考量: 避免隱性轉型。
情況: 當你為二元運算子時,如果左運算元為內建型態或 enum,則優先使用非成員
函式。
3. 封裝考量: 一般非成員函式的優點在於保證其無法存取私有成員。所以從封裝來看,
如果可以的話,非成員函式應該優先。
問題發生在當我們需要存取私有成員時會有兩個選擇: 一個是使用成員函
式,另一個則是使用 friend 的非成員函式。
情況一: 如果是一元運算子,或者是二元運算子但是兩個運算元的類別相
同時,我傾向用成員函式。主要是因為從屬性蠻明確的。
情況二: 如果是二元運算子且兩個運算元的類別不同。則此時看其兩運算
元角色是否一樣,例如其是否遵守交換律,也就是兩個運算元交
換位置是否會得到一樣的結果。如果遵守交換律我會選用非成員
函式 (加 friend),反之則通常是因為會修改到左運算元的內容
(例如 operator +=),此時我會使用成員函式。當然其他情況
就看自己覺得哪個合理 Orz.
依照我的想法,原 po 的 +, - , *, /, % 我會用非成員函式, +=, -=, *= 和 /= 會
用成員函式。不過我相信每個人看法一定有所差異。
> -------------------------------------------------------------------------- <
作者: Feis (坐吃山空) 看板: C_and_CPP
標題: Re: [問題] 關於運算子重載(operator overloading)
時間: Mon May 25 08:35:01 2015
推 wtchen: 所以若我要讓交換律成立,我得寫兩個非成員函式? 05/25 02:08
→ wtchen: const complex operator*(double a, BigNumber& b) 05/25 02:09
→ wtchen: 和const complex operator*(BigNumber& b, double a) ? 05/25 02:09
誠如原文所述,這個情況我個人想法是看 operator* 會否存取到 BigNumber 的私有成
員。如果不會的話,我會選非成員函式。如果會的話,因為這裡符合交換律我會選加
friend 的非成員函式。
所以無論如何我都會選用非成員函式的型式。
因此確實需要定義兩個函式 BigNumber operator*(double lhs, BigNumber rhs) 及
BigNumber operator*(BigNumber lhs, double rhs) [註1]
但是其中之一的實作可以由另外一個達成,例如我們已經實作好前者, 則後者可以這樣
實作:
BigNumber operator*(BigNumber lhs, double rhs) {
return rhs * lhs;
}
當然有另一種選擇是使用隱性轉型將 double 轉為 BigNumber 來解決交換律的問題。
但是因為違反我避免使用隱性轉型的原則所以我的想法是不傾向這樣的作法。
[註1] 這裡的 signature 因為 C++ 版本不同有不同適當的寫法。