【问题标题】:How to overload the operator++ in two different ways for postfix a++ and prefix ++a?对于后缀a++和前缀++a,如何以两种不同的方式重载operator++?
【发布时间】:2011-04-20 06:21:57
【问题描述】:

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

【问题讨论】:

标签: c++ operator-overloading


【解决方案1】:

我知道已经晚了,但我遇到了同样的问题并找到了一个更简单的解决方案。不要误会我的意思,这是相同的解决方案,因为上面的解决方案(由 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 方法中使用临时对象。

【讨论】:

  • 这不是标准的。后缀 operator++ 应该返回递增之前的值,而不是之后。
  • 这个答案不正确。临时是必需的。
【解决方案2】:

不同之处在于您为operator ++ 的重载选择了什么签名。

引用自相关article on this subject in the C++ FAQ(更多详情请前往此处):

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

P.S.:当我发现这一点时,我最初看到的只是 dummy 参数,但不同的返回类型实际上更有趣;他们可能会解释为什么++x 被认为比x++ 更高效一般

【讨论】:

    【解决方案3】:

    应该是这样的:

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

    【讨论】:

    • 此代码还显示了前缀与后缀的性能差异。如果您返回的对象不适合 CPU 寄存器,那么您正在执行昂贵的复制操作。如果您需要使用预先增加的值,这很好,但如果您不使用,postfix 会好得多。一个示例是您通常使用的迭代器:for(pos=c.begin(); ...; ++pos) {} 而不是 pos++
    • @Eric:除了中间的一个句子外,你一直都是正确的。它的前缀更好。
    • 为什么Number operator++ (int)不使用int作为参数?
    • @SeanLetendre:它实际上并没有采用 int 参数。它是一个假参数。但是 C++ 语言的设计者必须定义一种方法来区分前缀和后缀函数定义。这是他们做出的设计决定。
    • @EnricoMariaDeAngelis:语法区分了两者。 ++x 是前缀,因此调用operator++()x++ 是后缀,因此调用operator++(int)
    【解决方案4】:

    您有两种方法可以为类型 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 的封装
    • 您甚至可以将其应用于代码不属于您的类或结构。这是一种在不修改对象声明的情况下增强对象接口的非侵入式方法。

    【讨论】:

      【解决方案5】:

      这样声明:

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

      正确实施——不要搞乱每个人都知道他们所做的事情(增加然后使用,使用然后增加)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-31
        • 2017-10-18
        • 2023-04-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多