多載比較運算子

在前一章,我們學會了如何多載 I/O 運算子,一種非常常用的運算子種類。

今天我們要來多載 比較運算子,也是另一種常用的運算子種類。

多載這類的運算子讓我們可以互相比較兩個物件,或是針對一系列相同的物件進行排序。

多載 > 與 <

這邊我們就不介紹要如何多載運算子啦~ 想要複習的人可以往前面幾章看。

這邊我們就直接來看該如何多載一個 >< 的運算子。

class Dollars
{
private:
    int m_dollars;

public:
    Dollars(int dollars) : m_dollars{ dollars } {}

    friend bool operator< (const Dollars& d1, const Dollars& d2);
    friend bool operator> (const Dollars& d1, const Dollars& d2);
};

bool operator> (const Dollars& d1, const Dollars& d2)
{
    return d1.m_dollars > d2.m_dollars;
}

bool operator< (const Dollars& d1, const Dollars& d2)
{
    return d1.m_dollars < d2.m_dollars; 
}

int main()
{
    Dollars three_dollars{ 3 };
    Dollars one_dollar{ 1 };

    if (three_dollars > one_dollar)
        std::cout << "三塊 > 一塊\n";
    else
        std::cout << "三塊 < 一塊\n";

    return 0;
}

如果前面幾章有學好的人,這樣的程式碼應該是非常容易就可以看懂的!

我們可以利用同樣的方法,去多載 >=<= 這兩個運算子。

多載 == 與 !=

接著,我們用同樣的方法來多載 ==!= 運算子。

class Dollars
{
private:
    int m_dollars;

public:
    Dollars(int dollars)
    : m_dollars{ dollars }
    {}

    friend bool operator== (const Dollars& d1, const Dollars& d2);
    friend bool operator!= (const Dollars& d1, const Dollars& d2);
};

bool operator== (const Dollars& d1, const Dollars& d2)
{
    return d1.m_dollars == d2.m_dollars;
}

bool operator!= (const Dollars& d1, const Dollars& d2)
{
    return d1.m_dollars != d2.m_dollars;
}

int main()
{
    Dollars three_dollars{ 3 };
    Dollars one_dollar{ 1 };

    if (three_dollars == one_dollar)
        std::cout << "三塊 等於 一塊\n";
    else
        std::cout << "三塊 不等於 一塊\n";

    return 0;
}

幾乎是同樣的程式碼,只是將運算子的符號改變一下。

這樣一來,我們就多載了六個比較運算子了!

節省程式碼

雖然多載了六個運算子,但你有沒有覺得這些步驟很冗長?

其實我們可以透過已經多載的運算子去實作還沒多載的,來減少程式碼的冗長程度。

什麼意思呢?

比如說,我們可以透過 > 去多載 <

bool operator> (const Dollars& d1, const Dollars& d2)
{
    return d1.m_dollars > d2.m_dollars;
}

bool operator< (const Dollars& d1, const Dollars& d2)
{
    return !(d1 > d2);
}

注意到了嗎?其實 < 就是 > 的相反,因此我們可以使用 !(d1 > d2) 做到我們想做到的事。

你可能會說,誒啊結果都是一行程式碼啊,有差嗎?

在這個簡單的例子是這樣沒錯,但是在更複雜的類別中,有可能比較的邏輯也更加複雜,少的話十多行,多則百行。

在那樣的情況下,我們只需要實作出一項運算子就好啦!

結合 std::sort

一個需要多載比較運算子的常見應用包括 std::sort 的使用。

std::sort 讓我們可以對一個陣列做排序。

先來看一個簡單的例子:

int main()
{
    std::vector<int> vec{1, 5, 2, 7};
    std::sort(vec.begin(), vec.end());
    
    for (auto& element : vec)
    {
        std::cout << element << std::endl;
    }

    return 0;
}

印出的結果就會是:

1
2
5
7

假如今天我們有一個 Dollars 陣列,在有多載比較運算子的情況下,我們就可以輕鬆的使用 std::sort 做排序。

比如說:

int main()
{
    std::vector<Dollars> vec{1, 3, 2, 4};
    std::sort(vec.begin(), vec.end());
    
     for (auto& dollar : vec)
    {
        std::cout << dollar.getDollar() << std::endl;
    }
    return 0;
}

輸出的結果就會是:

1
2
3
4

如果我們沒有實作多載運算子,那我們就會看到一個常見的錯誤:

error: no match for 'operator<' (operand types are 'Dollars' and 'Dollars')
   45 |       { return *__it1 < *__it2; }
      |                ~~~~~~~^~~~~~~~

這個錯誤就是在說,C++ 不知道該如何比較兩個 Dollars 物件!

我們必須要提供函式 operator<,才能讓 C++ 知道應該如何比較。

總結

這篇我們又學到了一個多載運算子的實際應用啦!

在現實中,我們常常會需要多載這類的比較運算子來讓我們可以方便比較兩個相同的物件,或是做排序。

那麼下一章我們就繼續來看其他運算子的多載吧!

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