Overloading the increment and decrement operators (非常好)

原文: 

http://www.learncpp.com/cpp-tutorial/97-overloading-the-increment-and-decrement-operators/

 

 

 

Overloading the increment (++) and decrement (--) operators are pretty straightforward, with one small exception. There are actually two versions of the increment and decrement operators: a prefix increment and decrement (eg. ++nX; --nY;) and a postfix increment and decrement (eg. nX++; nY--;).

Because the increment and decrement operators modify their operands, they’re best overloaded as member functions. We’ll tackle the prefix versions first because they’re the most straightforward.

Overloading prefix increment and decrement

Prefix increment and decrement is overloaded exactly the same as any normal unary operator. We’ll do this one by example:

01class Digit
02{
03private:
04    int m_nDigit;
05public:
06    Digit(int nDigit=0)
07    {
08        m_nDigit = nDigit;
09    }
10 
11    Digit& operator++();
12    Digit& operator--();
13 
14    int GetDigit() const return m_nDigit; }
15};
16 
17Digit& Digit::operator++()
18{
19    // If our number is already at 9, wrap around to 0
20    if (m_nDigit == 9)
21        m_nDigit = 0;
22    // otherwise just increment to next number
23    else
24        ++m_nDigit;
25 
26    return *this;
27}
28 
29Digit& Digit::operator--()
30{
31    // If our number is already at 0, wrap around to 9
32    if (m_nDigit == 0)
33        m_nDigit = 9;
34    // otherwise just decrement to next number
35    else
36        --m_nDigit;
37 
38    return *this;
39}

Our Digit class holds a number between 0 and 9. We’ve overloaded increment and decrement so they increment/decrement the digit, wrapping around if the digit is incremented/decremented out range.

Note that we return *this. The overloaded increment and decrement operators return a Digit so multiple operators can be “chained” together. Consequently, we need to return an item of type Digit. Since these operators are implemented as member functions, we can just return *this, which is an item of type Digit!

 

Overloading postfix increment and decrement

Normally, functions can be overloaded when they have the same name but a different number and/or different type of parameters. However, consider the case of the prefix and postfix increment and decrement operators. Both have the same name (eg. operator++), are unary, and take one parameter of the same type. So how it is possible to differentiate the two when overloading?

The answer is that C++ uses a “dummy variable” or “dummy argument” for the postfix operators. This argument is a fake integer parameter that only serves to distinguish the postfix version of increment/decrement from the prefix version. Here is the above Digit class with both prefix and postfix overloads:

01class Digit
02{
03private:
04    int m_nDigit;
05public:
06    Digit(int nDigit=0)
07    {
08        m_nDigit = nDigit;
09    }
10 
11    Digit& operator++(); // prefix
12    Digit& operator--(); // prefix
13 
14    Digit operator++(int); // postfix
15    Digit operator--(int); // postfix
16 
17    int GetDigit() const return m_nDigit; }
18};
19 
20Digit& Digit::operator++()
21{
22    // If our number is already at 9, wrap around to 0
23    if (m_nDigit == 9)
24        m_nDigit = 0;
25    // otherwise just increment to next number
26    else
27        ++m_nDigit;
28 
29    return *this;
30}
31 
32Digit& Digit::operator--()
33{
34    // If our number is already at 0, wrap around to 9
35    if (m_nDigit == 0)
36        m_nDigit = 9;
37    // otherwise just decrement to next number
38    else
39        --m_nDigit;
40 
41    return *this;
42}
43 
44Digit Digit::operator++(int)
45{
46    // Create a temporary variable with our current digit
47    Digit cResult(m_nDigit);
48 
49    // Use prefix operator to increment this digit
50    ++(*this);             // apply operator
51 
52    // return temporary result 返回的只是暂时的没有被增加的副本,而this指针自己本身将会被增加在之后
53    return cResult;       // return saved state
54}
55 
56Digit Digit::operator--(int)
57{
58    // Create a temporary variable with our current digit
59    Digit cResult(m_nDigit);
60 
61    // Use prefix operator to increment this digit
62    --(*this);             // apply operator
63 
64    // return temporary result 返回的只是暂时的没有被减小的副本,而this指针自己本身将会被减小在之后
65    return cResult;       // return saved state
66}
67 
68int main()
69{
70    Digit cDigit(5);
71    ++cDigit; // calls Digit::operator++();
72    cDigit++; // calls Digit::operator++(int);
73 
74    return 0;
75}

There are a few interesting things going on here. First, note that we’ve distinguished the prefix from the postfix operators by providing an integer dummy parameter on the postfix version. Second, because the dummy parameter is not used in the function implementation, we have not even given it a name. This tells the compiler to treat this variable as a placeholder, which means it won’t warn us that we declared a variable but never used it.

Third, note that the prefix and postfix operators do the same job — they both increment or decrement the class. The difference between the two is in the value they return. The overloaded prefix operators return the class after it has been incremented or decremented. Consequently, overloading these is fairly straightforward. We simply increment or decrement our member variables, and then return *this.

The postfix operators, on the other hand, need to return the state of the class before it is incremented or decremented. This leads to a bit of a conundrum — if we increment or decrement the class, we won’t be able to return the state of the class before it was incremented or decremented. On the other hand, if we return the state of the class before we increment or decrement it, the increment or decrement will never be called.

The typical way this problem is solved is to use a temporary variable that holds the value of the class before it is incremented or decremented. Then the class itself can be incremented or decremented. And finally, the temporary variable is returned to the caller. In this way, the caller receives a copy of the class before it was incremented or decremented, but the class itself is incremented or decremented. Note that this means the return value of the overloaded operator much be a non-reference, because we can’t return a reference to a local variable that will be destroyed when the function exits. Also note that this means the postfix operators are typically less efficient than the prefix operators because of the added overhead of instantiating a temporary variable and returning by value instead of reference.

Finally, note that we’ve written the post-increment and post-decrement in such a way that it calls the pre-increment and pre-decrement to do most of the work. This cuts down on duplicate code, and makes our class easier to modify in the future.

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值