利用 Friend 多載運算子

在前一章 多載運算子基本介紹 中,我們簡單介紹了多載運算子這個概念,但我們沒有講解該如何實作多載運算子。

這章我們就要來看看到底該如何實作多載運算子!

前言

在 C++ 中最常用的運算子應該就是加 (+)、減 (-)、乘 (*) 、除 (/) 了。這些運算子都是二元的,意思是它們需要兩個運算元,一個在運算子的左側,一個在右側。

也因此,數一數二常見被多載的運算子就是加減乘除。當然還有其他常見的,但是在我們的例子中,我們會首先用加號 + 當作範例。

我們基本上有三種方式可以做到運算子多載:

  1. 友元函數 friend function
  2. 普通函數 normal function
  3. 成員函數 member function

在這篇文章中,我們將重點放在利用友函數 friend function 進行運算子多載,這對於大多數二元運算子來說比較常見。

接下來的幾篇,我們會再介紹其他兩種方法,並會在最後講到什麼時候該使用哪一種方法!

問題

前一章說到,有時候我們可能會想要使用一個沒有被定義的運算子使用方式,這樣程式碼就會出錯。

舉個例子大家會比較好懂:

class Money
{
private:
    int _dollars {};

public:
    Money(int dollars) : _dollars{ dollars } { }
    int getDollars() { return _dollars; }
};

int main()
{
    Money money1{ 1 };
    Money money2{ 2 };

    // 無法執行加法
    std::cout << money1 + money2 << std::endl;

    return 0;
}

在這個程式碼中,我們自己定義了一個類別 Money,並在最後嘗試將兩個類別相加。

想當然,程式碼會報錯,因為我們沒有定義可以將 Money 相加的運算子使用方法。

這樣要如何解決呢?

解決方法

我們直接來看解決辦法:

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;
}

這樣的程式碼最後會輸出:

3

我們來看一下我們在這段程式碼中做了什麼事。

首先,我們知道如果要多載加號運算子,我們需要自己去多載 operator+ 這個函數。

而這就是第 13 行所做的,將兩個 Money 物件中的成員 dollars 相加,最後返回型態 Money

另外,我們在第 10 行宣告函數 operator+ 為類別 Money 的友函數,因此它才可以直接取得私有成員 dollars

同樣道理,你們可以自己去試著做做看其他運算子,比如說減法、乘法等等。

不同型態的運算元

好了,現在我們可以將兩個同樣是 Money 類別的物件相加了。但會不會有時我們想要做到類似這樣的事呢?

int dollar = 4;
Money money{1};

// 想做以下這個
money + 4;

當然有可能!

想要做到這件事,我們就必續再多載一次運算子:

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);
    friend Money operator+(const Money& m1, const int dollar);
};

Money operator+(const Money& m1, const Money& m2)
{
    return m1._dollars + m2._dollars;
}

Money operator+(const Money& m1, const int dollar)
{
    return m1._dollars + dollar;
}

這樣我們就可以做到 money + 4 這件事啦!

但是有一件事非常重要!money + 44 + money 兩個用到的函數是不同的!這是因為加號左右兩邊的運算元型態並不相同。

因此如果想要做到 4 + money ,我們必須再多載一次:

Money operator+(const int dollar, const Money& m1)
{
    return m1._dollars + dollar;
}

總結

這篇我們終於學到可以如何多載一個運算子了!

多載運算子在進階的類別應用,或是在實際軟體世界中是非常常見的應用喔,因此這個概念非常重要!

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