利用成員函數多載運算子

在前一章 利用普通函數多載運算子 中,我們講到了第二種方法多載運算子的方法,在那一章中,我們介紹了如何用普通函數多載運算子。

這章我們要來看看第三個也是最後一個方法,也就是利用成員函數多載運算子!

實作

一樣,我們不在這章討論為什麼我們會需要去多載一個運算子,因為在前一章我們已經討論過了。

因此這章,我們就跳過那些已經討論過的問題,直接來看如何實作。

在討論如何使用成員函數多載運算子之前,我們先再來看一次該如何使用 Friend 多載運算子。

利用 Friend
class 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 多載運算子的方式非常相似,只需要更改三個地方:

  1. 運算子函數 operator+ 要從 friend 改為成員函數,也就是說將 friend operator+ 改為 Money::operator+
  2. 移除第一個參數,因為第一個參數已經變成 *this 物件
  3. 在函數內不需要再透過物件取得特徵,也就是說 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? 的討論。這邊就不多做介紹。

成員函數的局限

接著我們來看成員函數對於堆載運算子的局限性。

  1. 無法多載 I/O 運算子,比如說 <<>>
  2. 無法多載第一個參數不是自己類別的運算子函數,比方說 operator+(int val, Money money)

第一個點我們以後會專門在另一章教大家該如何多載 I/O 運算子,並且說明為什麼成員函數無法多載這類運算子。

第二點的話就比較直覺了,因為第一個參數必須為同一個類別,才可以被編譯器轉換為隱藏的 *this 指標。

因此,我們可以做這樣簡單的結論:

總結

這篇讓我們終於把所有用來多載一個運算子的方法學完了!

接下來我會帶大家來看看除了簡單的加減乘除外,我們還可以多載哪些常用的運算子!

那這篇就到這裡啦!有學到東西的話歡迎留五星評價喔!