章节目录

重载一元运算符+、-和!

本节阅读量:

与迄今为止看到的运算符不同,正(+)、负(-)和逻辑not(!)运算符都是一元运算符,这意味着它们只对一个操作数进行操作。因为它们只对应用它们的对象进行操作,所以通常一元运算符重载被实现为成员函数。所有三个操作符都以相同的方式实现。

让我们看看如何在前面的示例中使用的Cents类上实现操作符:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <iostream>

class Cents
{
private:
    int m_cents {};
 
public:
    Cents(int cents): m_cents{cents} {}
 
    // 重载 -Cents 作为成员函数
    Cents operator-() const;

    int getCents() const { return m_cents; }
};
 
// 注: 这个函数是成员函数!
Cents Cents::operator-() const
{
    return -m_cents; // 因为返回类型是Cents,这里有个int到Cents的隐式转换
}

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对象上调用它)。

注意,负操作符和减法操作符之间没有混淆,因为它们具有不同数量的参数。

这是另一个例子。“operator!”是逻辑求反运算符——如果表达式的计算结果为“true”,则为“operator!”将返回false,反之亦然。我们通常将此应用于布尔变量,以测试它们是否为真:

1
2
3
4
if (!isHappy)
    std::cout << "I am not happy!\n";
else
    std::cout << "I am so happy!\n";

对于整数,0计算为false,其他任何值计算为true,所以“operator!”应用于整数时,如果整数值为0,则返回true,否则返回false。

扩展概念,我们可以说“operator!”,如果对象的状态为“false”、“zero”或默认初始化状态是什么,则应计算为true。

下面的示例显示对于用户定义的Point类进行“operator!”重载:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#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}
    {
    }
 
    // 转换成一个负的对应的量
    Point operator- () const;

    // 如果为原点,则返回true
    bool operator! () const;
 
    double getX() const { return m_x; }
    double getY() const { return m_y; }
    double getZ() const { return m_z; }
};

// 转换成一个负的对应的量
Point Point::operator- () const
{
    return { -m_x, -m_y, -m_z };
}

// 如果为原点,则返回true
bool Point::operator! () const
{
    return (m_x == 0.0 && m_y == 0.0 && m_z == 0.0);
}

int main()
{
    Point point{}; // 默认构造函数会初始化为 (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重载的“operator!”,如果对应的对象在坐标(0.0、0.0、0.0),则返回布尔值“true”。因此,上述代码生成结果:

1
point is set at the origin.

21.4 使用成员函数重载运算符

上一节

21.6 重载比较运算符

下一节