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

image

这应该很简单。我们的重载负运算符(-)是一个以成员函数形式实现的一元运算符,因此它不接受参数(它作用于*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”。因此,上述代码将产生以下结果:

image


测验时间

为Point类实现重载的一元运算符+。一元运算符+仅返回其操作数(不将负值转正)。

显示解决方案

显而易见的解决方案如下:

Point Point::operator+ () const
{
    return { m_x, m_y, m_z };
}

但由于我们要返回的点恰好就是当前操作的点,因此以下写法同样有效:

Point Point::operator+ () const
{
    return *this;
}

请注意,这里我们返回的是按值传递的副本而非常量引用。这是因为该函数的使用者很可能期望返回的对象是可修改的。

posted @ 2026-01-22 17:07  游翔  阅读(0)  评论(0)    收藏  举报