21-6 重载一元运算符 +、- 和 !
重载一元运算符
与之前见过的运算符不同,正号(+)、负号(-)和逻辑非(!)运算符均为一元运算符,这意味着它们仅对一个操作数进行操作。由于它们仅作用于被应用的对象,通常将一元运算符重载实现为成员函数。这三种运算符的实现方式完全相同。
让我们看看如何在先前示例中使用的 Cents 类上实现 - 运算符:
#include <iostream>
class Cents
{
private:
int m_cents {};
public:
Cents(int cents): m_cents{cents} {}
// Overload -Cents as a member function
Cents operator-() const;
int getCents() const { return m_cents; }
};
// note: this function is a member function!
Cents Cents::operator-() const
{
return -m_cents; // since return type is a Cents, this does an implicit conversion from int to Cents using the Cents(int) constructor
}
int main()
{
const Cents nickle{ 5 };
std::cout << "A nickle of debt is worth " << (-nickle).getCents() << " cents\n";
return 0;
}

这应该很简单。我们的重载负运算符(-)是一个以成员函数形式实现的一元运算符,因此它不接受参数(它作用于*this对象)。它返回一个Cents对象,该对象是原始Cents值的负值。由于-运算符不会修改Cents对象,我们可以(也应该)将其定义为const函数(这样它就可以在const Cents对象上调用)。
请注意,负值运算符-与减号运算符-之间不会产生混淆,因为它们的参数数量不同。
下面是另一个示例。! 运算符是逻辑取反运算符——若表达式评估结果为“true”,则 operator! 将返回 false,反之亦然。我们常将其应用于布尔变量以测试其真值性:
if (!isHappy)
std::cout << "I am not happy!\n";
else
std::cout << "I am so happy!\n";
对于整数而言,0 评估为 false,其余值均评估为 true,因此当运算符 ! 应用于整数时,若整数值为 0 则返回 true,否则返回 false。
由此概念延伸,当对象状态为“false”、“零”或任何默认初始化状态时,运算符!都应评估为true。
以下示例展示了用户自定义Point类中运算符和运算符!的重载实现:
#include <iostream>
class Point
{
private:
double m_x {};
double m_y {};
double m_z {};
public:
Point(double x=0.0, double y=0.0, double z=0.0):
m_x{x}, m_y{y}, m_z{z}
{
}
// Convert a Point into its negative equivalent
Point operator- () const;
// Return true if the point is set at the origin
bool operator! () const;
double getX() const { return m_x; }
double getY() const { return m_y; }
double getZ() const { return m_z; }
};
// Convert a Point into its negative equivalent
Point Point::operator- () const
{
return { -m_x, -m_y, -m_z };
}
// Return true if the point is set at the origin, false otherwise
bool Point::operator! () const
{
return (m_x == 0.0 && m_y == 0.0 && m_z == 0.0);
}
int main()
{
Point point{}; // use default constructor to set to (0.0, 0.0, 0.0)
if (!point)
std::cout << "point is set at the origin.\n";
else
std::cout << "point is not set at the origin.\n";
return 0;
}
该类的重载运算符!若将Point设置为坐标(0.0, 0.0, 0.0)的默认值,则返回布尔值“true”。因此,上述代码将产生以下结果:

测验时间
为Point类实现重载的一元运算符+。一元运算符+仅返回其操作数(不将负值转正)。
显示解决方案
显而易见的解决方案如下:
Point Point::operator+ () const { return { m_x, m_y, m_z }; }但由于我们要返回的点恰好就是当前操作的点,因此以下写法同样有效:
Point Point::operator+ () const { return *this; }请注意,这里我们返回的是按值传递的副本而非常量引用。这是因为该函数的使用者很可能期望返回的对象是可修改的。

浙公网安备 33010602011771号