如何以两种不同的方式为后缀a ++和前缀++ a重载operator ++?


Answers:


165

应该看起来像这样:

class Number 
{
    public:
        Number& operator++ ()     // prefix ++
        {
           // Do work on this.   (increment your object here)
           return *this;
        }

        // You want to make the ++ operator work like the standard operators
        // The simple way to do this is to implement postfix in terms of prefix.
        //
        Number  operator++ (int)  // postfix ++
        {
           Number result(*this);   // make a copy for result
           ++(*this);              // Now use the prefix version to do the work
           return result;          // return the copy (the old) value.
        }
}; 

15
此代码还显示了前缀与后缀的性能差异。如果您要返回的对象不适合CPU寄存器,则您正在执行昂贵的复制操作。如果您需要使用预先增加的值,这很好,但是如果不需要,则后缀要好得多。一个示例是一个迭代器,通常在其中使用:for(pos = c.begin(); ...; ++ pos){}而不是pos ++
Eric 2010年

22
@Eric:除了中间的一个句子外,您一直都可以正确校正。它的前缀更好。
马丁·约克

6
为什么不Number operator++ (int)使用a int作为参数?
肖恩·莱顿德里

10
@SeanLetendre:实际上并没有int参数。它是一个伪参数。但是C ++语言的设计者必须定义一种区分前缀和后缀函数定义的方法。这是他们做出的设计决定。
马丁·约克

2
@EnricoMariaDeAngelis:语法将两者区分开。++x是前缀,因此调用operator++()x++而是后缀,因此调用operator++(int)
Martin York

34

区别在于您为的过载选择了什么签名operator ++

C ++ FAQ中与此主题相关的文章中引用(有关更多详细信息,请转到此处):

class Number {
  public:
    Number& operator++ ();     // prefix ++: no parameter, returns a reference
    Number  operator++ (int);  // postfix ++: dummy parameter, returns a value
};

PS:当我发现这一点时,最初看到的只是虚拟参数,但是不同的返回类型实际上更有趣;他们可能解释为什么为什么++xx++ 一般效率高。


17

您可以通过两种方式重载类型T的两个(前缀/后缀)++运算符:

对象方法:

这是使用“通用” OOP习惯用法的最简单方法。

class T
{
    public :
        T & operator++() // ++A
        {
            // Do increment of "this" value
            return *this ;
        }

        T operator++(int) // A++
        {
           T temp = *this ;
           // Do increment of "this" value
           return temp ;
        }
} ;

对象非成员函数:

这是执行此操作的另一种方法:只要这些函数也与它们所引用的对象位于同一名称空间中,则在编译器搜索要处理的函数++t ;t++ ;代码时将考虑它们:

class T
{
    // etc.
} ;


T & operator++(T & p_oRight) // ++A
{
   // Do increment of p_oRight value
   return p_oRight ;
}

T operator++(T & p_oRight, int) // A++
{
   T oCopy ;
   // Copy p_oRight into oCopy
   // Do increment of p_oRight value
   return oCopy ;
}

重要的是要记住,从C ++的观点(包括C ++编译器的观点)来看,那些非成员函数仍然是T接口的一部分(只要它们在同一名称空间中)。

非成员函数表示法有两个潜在的优点:

  • 如果您在不让它们成为T的朋友的情况下设法编码它们,那么您增加了T的封装
  • 您甚至可以将其应用于您不拥有其代码的类或结构。这是在不修改对象声明的情况下增强对象接口的非介入方式。

1

这样声明:

class A
{
public:
    A& operator++();    //Prefix (++a)
    A operator++(int); //Postfix (a++)

};

正确实施-不要搞乱大家都知道的事情(先递增后使用,先递增后使用)。


-2

我知道已经晚了,但是我遇到了同样的问题,找到了一个更简单的解决方案。不要误会我的意思,这与排名第一的解决方案相同(由Martin York发布)。这只是简单一点。一点点。这里是:

class Number
{
        public:

              /*prefix*/  
        Number& operator++ ()
        {
            /*Do stuff */
            return *this;
        }

            /*postfix*/
        Number& operator++ (int) 
        {
            ++(*this); //using the prefix operator from before
            return *this;
        }
};

上面的解决方案比较简单,因为它在postfix方法中不使用临时对象。


6
这不是标准的。后缀运算符++应该在递增之前而不是之后返回值。
Kuilin Li

这个答案是不正确的。临时是必需的。
瑞安·奎因
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.