C++重载自增与自减操作符

自增运算符++与自减运算符--都是一元操作符,其前置和后置两种形式都可以被重载。

有了前面介绍操作符重载的基础,我们直接以示例的形式讲解重载自增和自减操作符的方法。
#include <iostream>
#include <iomanip>
using namespace std;

class stopwatch
{
public:
    stopwatch(){ min = 0; sec = 0;}
    void setzero() { min = 0; sec = 0; }
    stopwatch run();               // 运行
    stopwatch operator++();        // ++ i
    stopwatch operator++(int);     // i ++
    friend ostream & operator<<( ostream &, const stopwatch &);
private:
    int min; //分钟
    int sec; //秒钟
};

stopwatch stopwatch::run()
{
    ++ sec;
    if( sec == 60 )
    {
        min ++;
        sec = 0;
    }
    return * this;
}

stopwatch stopwatch::operator++()
{
    return run();
}

stopwatch stopwatch::operator++(int n)
{
    stopwatch s = *this;
    run();
    return s;
}

ostream & operator<<( ostream & out, const stopwatch & s)
{
    out<< setfill('0')<< setw(2) << s.min << ":" <<setw(2) << s.sec;
    return out;
}

int main()
{
    stopwatch s1, s2;
    s1 = s2 ++;
    cout << " s1 "<< s1 <<endl;
    cout << " s2 "<< s2 <<endl;
    s1.setzero();
    s2.setzero();
    s1 = ++ s2;
    cout << " s1 "<< s1 <<endl;
    cout << " s2 "<< s2 <<endl;
    return 0;
}
在本例中,我们定义了一个简易的 stopwatch 秒表类,该类有两个私有成员变量 min 和 sec,分别代表分钟和秒钟。类中声明的 setzero() 成员函数用于秒表清零,run() 函数用于描述秒针向前进一秒的动作,之后是三个操作符重载函数,前两个分别是重载自增操作符,最后一个是重载输出操作符。

我们来仔细看一下各个函数的具体实现:
  • 先看 run() 函数,该函数一开始让秒针自增,如果此时自增结果等于 60 了,则应该进位,分钟加 1,秒针置零;
  • 再看一下 operator++() 函数,该函数时实现自增的前置形式,因此直接返回 run() 函数运行结果即可。
  • 对于 operator++(int n) 函数,这是实现自增的后置形式,自增的后置形式的返回值是对象本身,但是之后再次使用该对象时,该对象自增了,因此在该函数的函数体中,先将对象保存,然后调用一次 run() 函数,再将先前保存的对象返回。在这个函数中,参数 n 是没有任何意义的,它的存在只是为了区分是前置还是后置形式。
  • 最后我们还重载了输出操作符,以便于我们打印计时结果,在函数体中我们使用了输出控制函数,这些函数将在输入输出流那一章会有介绍。

这个程序运行结果如下:

s1 00:00
s2 00:01
s1 00:01
s2 00:01

对照主函数分析程序的运行结果,主函数一开始定义了两个对象 s1 和 s2,第一次操作s1 = s2 ++;采用的是后置形式,这可以理解为s1 = s2并且 s2 自增,输出结果是 s1 处于置零状态,s2 自增了一秒钟。之后两个对象都清零,清零后s1=++s2;,可以理解为 s2 自增并将自增结果赋给 s1,如此一来两个对象都自增一秒钟。

自减操作符的重载跟自增操作符类似,这里就不再赘述了。