重载比较运算符
重载比较运算符相对简单,因为它们遵循我们在重载其他运算符时看到的相同模式。
因为比较运算符都是不修改左操作数的二元运算符,所以我们将使重载的比较运算符声明为友元函数。
这是一个带有重载运算符==和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;
}