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

猜你喜欢

转载自blog.csdn.net/qq_41879485/article/details/83079621