1. 程式人生 > >C++基礎教程面向物件(學習筆記(24))

C++基礎教程面向物件(學習筆記(24))

過載比較運算子

過載比較運算子相對簡單,因為它們遵循我們在過載其他運算子時看到的相同模式。

因為比較運算子都是不修改左運算元的二元運算子,所以我們將使過載的比較運算子宣告為友元函式。

這是一個帶有過載運算子==和operator!=的Car類的示例。

#include <iostream>
#include <string>
 
class Car
{
private:
    std::string m_make;
    std::string m_model;
 
public:
    Car(std::string make, std::string model)
        : m_make(make), m_model(model)
    {
    }
 
    friend bool operator== (const Car &c1, const Car &c2);
    friend bool operator!= (const Car &c1, const Car &c2);
};
 
bool operator== (const Car &c1, const Car &c2)
{
    return (c1.m_make== c2.m_make &&
            c1.m_model== c2.m_model);
}
 
bool operator!= (const Car &c1, const Car &c2)
{
    return !(c1== c2);
}
 
int main()
{
    Car corolla ("Toyota", "Corolla");
    Car camry ("Toyota", "Camry");
 
    if (corolla == camry)
        std::cout << "a Corolla and Camry are the same.\n";
 
    if (corolla != camry )
        std::cout << "a Corolla and Camry are not the same.\n";
 
    return 0;
}

這裡的程式碼應該是很直接的。因為operator!=的結果與operator 相反,我們根據operator定義operator!=,這有助於使事情更簡單,更無錯誤,並減少我們編寫的程式碼量。

operator<和operator>怎麼樣?汽車比另一輛汽車更大或更小的意義是什麼?我們通常不會這樣考慮汽車。由於operator <和operator>的結果不會立即直觀,因此最好不要定義這些運算子。

建議:不要定義對您的類沒有意義的過載運算子。

但是,上述建議有一個共同的例外。如果我們想要對汽車列表進行排序怎麼辦?在這種情況下,我們可能希望過載比較運算子以返回您最有可能要排序的成員(或成員)。例如,過載的operator<對於 Cars可能會按字母順序基於品牌和型號進行排序。

標準庫中的一些容器類(包含其他類的集合的類)需要過載的operator<所以它們可以保持元素的排序。

以下是過載operator>,operator <,operator> =和operator <=的不同示例:

#include <iostream>
 
class Cents
{
private:
    int m_cents;
 
public:
    Cents(int cents) { m_cents = cents; }
 
    friend bool operator> (const Cents &c1, const Cents &c2);
    friend bool operator<= (const Cents &c1, const Cents &c2);
 
    friend bool operator< (const Cents &c1, const Cents &c2);
    friend bool operator>= (const Cents &c1, const Cents &c2);
};
 
bool operator> (const Cents &c1, const Cents &c2)
{
    return c1.m_cents > c2.m_cents;
}
 
bool operator>= (const Cents &c1, const Cents &c2)
{
    return c1.m_cents >= c2.m_cents;
}
 
bool operator< (const Cents &c1, const Cents &c2)
{
    return c1.m_cents < c2.m_cents;
}
 
bool operator<= (const Cents &c1, const Cents &c2)
{
    return c1.m_cents <= c2.m_cents;
}
 
int main()
{
    Cents dime(10);
    Cents nickle(5);
 
    if (nickle > dime)
        std::cout << "a nickle is greater than a dime.\n";
    if (nickle >= dime)
        std::cout << "a nickle is greater than or equal to a dime.\n";
    if (nickle < dime)
        std::cout << "a dime is greater than a nickle.\n";
    if (nickle <= dime)
        std::cout << "a dime is greater than or equal to a nickle.\n";
 
 
    return 0;
}

這也非常簡單。

注意,這裡也有一些冗餘。operator>和operator <=是邏輯對立面,因此可以用另一個來定義。operator <和operator> =也是邏輯對立面,一個可以用另一個來定義。在這種情況下,我選擇不這樣做,因為函式定義非常簡單,函式名中的比較運算子與return語句中的比較運算子可以很好地對齊。

Quiz Time:

1)對於上面的Cents示例,根據其他過載運算子重寫運算子<和<=。

解決方案

#include <iostream>
 
class Cents
{
private:
	int m_cents;
 
public:
	Cents(int cents) { m_cents = cents; }
 
	friend bool operator> (const Cents &c1, const Cents &c2);
	friend bool operator<= (const Cents &c1, const Cents &c2);
 
	friend bool operator< (const Cents &c1, const Cents &c2);
	friend bool operator>= (const Cents &c1, const Cents &c2);
};
 
bool operator> (const Cents &c1, const Cents &c2)
{
	return c1.m_cents > c2.m_cents;
}
 
bool operator>= (const Cents &c1, const Cents &c2)
{
	return c1.m_cents >= c2.m_cents;
}
 
// <是> =的邏輯相反,所以我們可以> =並反轉
bool operator< (const Cents &c1, const Cents &c2)
{
	return !(c1 >= c2);
}
 
// <= 是>的邏輯相反,所以我們可以做>並反轉結
bool operator<= (const Cents &c1, const Cents &c2)
{
	return !(c1 > c2);
}
 
int main()
{
	Cents dime(10);
	Cents nickle(5);
 
	if (nickle > dime)
		std::cout << "a nickle is greater than a dime.\n";
	if (nickle >= dime)
		std::cout << "a nickle is greater than or equal to a dime.\n";
	if (nickle < dime)
		std::cout << "a dime is greater than a nickle.\n";
	if (nickle <= dime)
		std::cout << "a dime is greater than or equal to a nickle.\n";
 
 
	return 0;
}

2)將過載的運算子<<和operator <新增到本課程頂部的Car類,以便以下程式編譯:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
 
int main()
{
	std::vector<Car> v;
	v.push_back(Car("Toyota", "Corolla"));
	v.push_back(Car("Honda", "Accord"));
	v.push_back(Car("Toyota", "Camry"));
	v.push_back(Car("Honda", "Civic"));
 
	std::sort(v.begin(), v.end()); // 要求超載operator<
 
	for (auto &car : v)
		std::cout << car << '\n'; //要求超載 operator<<
 
	return 0;
}

該程式應產生以下輸出: (Honda,Accord) (Honda,Civic) (Toyota,Camry) (Toyota,Corolla) 解決方案:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
 
class Car
{
private:
	std::string m_make;
	std::string m_model;
 
public:
	Car(std::string make, std::string model)
		: m_make(make), m_model(model)
	{
	}
 
	friend bool operator== (const Car &c1, const Car &c2);
	friend bool operator!= (const Car &c1, const Car &c2);
	friend std::ostream& operator<< (std::ostream& out, const Car & c)
	{
		out << '(' << c.m_make << ", " << c.m_model << ')';
		return out;
	}
 
	// h/t to reader Olivier for this version of the function
	friend bool operator<(const Car &c1, const Car &c2)
	{
		if (c1.m_make == c2.m_make) //如果汽車是一樣的...
			return c1.m_model < c2.m_model; //然後比較 m_model
		else
			return c1.m_make < c2.m_make; // 否則比較兩個m_make
	}
};
 
bool operator== (const Car &c1, const Car &c2)
{
	return (c1.m_make == c2.m_make &&
		c1.m_model == c2.m_model);
}
 
bool operator!= (const Car &c1, const Car &c2)
{
	return !(c1 == c2);
}
 
int main()
{
	std::vector<Car> v;
	v.push_back(Car("Toyota", "Corolla"));
	v.push_back(Car("Honda", "Accord"));
	v.push_back(Car("Toyota", "Camry"));
	v.push_back(Car("Honda", "Civic"));
 
	std::sort(v.begin(), v.end()); // 要求超載 Car::operator<
 
	for (auto &car : v)
		std::cout << car << '\n'; // 要求超載Car::operator<<
 
	return 0;
}