利用成員函數多載運算子
在前一章 利用普通函數多載運算子 中,我們講到了第二種方法多載運算子的方法,在那一章中,我們介紹了如何用普通函數多載運算子。
這章我們要來看看第三個也是最後一個方法,也就是利用成員函數多載運算子!
實作
一樣,我們不在這章討論為什麼我們會需要去多載一個運算子,因為在前一章我們已經討論過了。
因此這章,我們就跳過那些已經討論過的問題,直接來看如何實作。
在討論如何使用成員函數多載運算子之前,我們先再來看一次該如何使用 Friend 多載運算子。
利用 Friendclass Money { private: int _dollars {}; public: Money(int dollars) : _dollars{ dollars } {} int getDollars() const { return _dollars; } friend Money operator+(const Money& m1, const Money& m2); }; Money operator+(const Money& m1, const Money& m2) { return m1._dollars + m2._dollars; } int main() { Money money1{ 1 }; Money money2{ 2 }; Money money3{ money1 + money2 }; std::cout << money3.getDollars() << std::endl; return 0; }
其實利用成員函數和利用 Friend 多載運算子的方式非常相似,只需要更改三個地方:
- 運算子函數
operator+
要從 friend 改為成員函數,也就是說將friend operator+
改為Money::operator+
。 - 移除第一個參數,因為第一個參數已經變成 *this 物件。
- 在函數內不需要再透過物件取得特徵,也就是說
m1._dollars
改成_dollars
。
我們按照上面這三步驟直接來做更改。
利用成員函數class Money { private: int _dollars {}; public: Money(int dollars) : _dollars{ dollars } {} int getDollars() const { return _dollars; } Money operator+(const Money m); }; Money Money::operator+(const Money m) { return _dollars + m._dollars; } int main() { Money money1{ 1 }; Money money2{ 2 }; Money money3{ money1 + money2 }; std::cout << money3.getDollars() << std::endl; return 0; }
我們來討論一下第 22 行究竟發生了什麼事。
當程式執行到第 22 行時,money1 + money2
會轉變成 money1.operator+(money2)
。雖然說參數只剩下一個,但是在 this 指標 那篇中,我們學到了成員函數的運作邏輯。我們知道編譯器會將 money1
轉變為隱藏的 *this 指標,並提供給函數進行下一步運算。
該使用那種方式
如果利用 Friend 和利用成員函數兩種方式都可以做到多載運算子,那我們該用哪個方法呢?
其實,這兩種方法都有各自的局限性。
Friend 的局限
不是所有運算子都可以透過 Friend 多載,比如說 =
、->
、()
和 []
。
想知道更多的話可以看這篇 Why can’t we overload the assignment operator using the friend function? 的討論。這邊就不多做介紹。
成員函數的局限
接著我們來看成員函數對於堆載運算子的局限性。
- 無法多載 I/O 運算子,比如說
<<
、>>
。 - 無法多載第一個參數不是自己類別的運算子函數,比方說
operator+(int val, Money money)
。
第一個點我們以後會專門在另一章教大家該如何多載 I/O 運算子,並且說明為什麼成員函數無法多載這類運算子。
第二點的話就比較直覺了,因為第一個參數必須為同一個類別,才可以被編譯器轉換為隱藏的 *this 指標。
因此,我們可以做這樣簡單的結論:
總結
這篇讓我們終於把所有用來多載一個運算子的方法學完了!
接下來我會帶大家來看看除了簡單的加減乘除外,我們還可以多載哪些常用的運算子!
那這篇就到這裡啦!有學到東西的話歡迎留五星評價喔!