为什么我不能像某些ClassObject ++ 5那样在后缀运算符++中使用伪参数?

时间:2019-06-04 08:29:38

标签: c++ operator-overloading

我知道我可以在后缀运算符++中将虚拟int用作someClassObject.operator++(5),但是为什么不能像someClassObject++5那样使用它呢?我问这个问题是因为operator+可以像someClassObject1 + someClassObject2这样使用。

{
public:

    test(int x, string y) : x(x), y(y){}
    test() :x(0), y("") {};

    //skiping some code for copy constructor and assignment operator overload

    test operator++(int x)
    {
        test a(*this);
        a.x += x;
        ++(*this);
        return a;
    }

    friend ostream& operator<<(ostream& ost, const test& test)
    {
        ost << test.x << " , " << test.y;
        return ost;
    }


    int x;
    string y;
};

int main()
{
    test t1(5, "testing");
    int x = 10;
    cout << t1.operator++(x) << endl;
    //the above line of code works but the line below gives error.
    t1++x;
    return 0;
}

我期望t1.operator++(5)t1++5都可以以相同的方式工作。

2 个答案:

答案 0 :(得分:11)

由于最大蒙克法则规则,表达式

t1++x

被解析为

t1 ++ x

分组

(t1 ++) x

这没有任何意义;就像t1 x毫无意义。

答案 1 :(得分:0)

  

我知道我可以在postfix运算符++中将虚拟int用作someClassObject.operator ++(5),但是为什么不能像someClassObject ++ 5那样使用它呢?

因为标准说So™。

由于C ++代码的解析和编译方式,后缀++--的工作原理有所不同。

我们来看看C++11 standard [draft]

  

13.5.1一元运算符[over.unary]

     

[...]有关后缀一元运算符++--的说明,请参见13.5.7。

好的,因此++--被视为一元运算符(即接受一个操作数)。类似于1 ++ 2的事物意味着++是二进制运算符(即,接受两个操作数)。但是没有二进制++运算符。后缀++一样被重载,但实际上并没有被解析为一个。让我们回顾一下标准。

  

13.3.1.2表达式[over.match.oper]

中的运算符      

如果操作数的类型是类或枚举,则可能会声明一个用户定义的运算符函数来实现此运算符,否则可能需要用户定义的转换才能转换操作数为适合于内置运算符的类型。在这种情况下,重载解析用于确定要调用哪个操作员功能或内置操作员以实现该操作员。因此,首先将运算符符号转换为表11中概述的等效函数调用符号(其中@表示指定子句中涉及的运算符之一)。

 Table 11 — Relationship between operator and function call notation 
Subclause  | Expression | As member function | As non-member function
                           [...]
13.5.2     | a@b        | (a).operator@(b)   | operator@ (a, b)
                           [...]
13.5.7     | a@         | (a).operator@(0)   | operator@ (a, 0)

(添加了重点)
someClassObject是一个类,并且声明了用户定义的运算符函数(test operator++(int x)),因此此特定子句适用于您的情况。 < / p>

首先,我在第13.5.2节中添加了该行,以消除任何疑问。第13.5.2节处理二进制运算符。但是正如我们已经确定的那样,C ++中没有二进制++运算符,唯一的后缀++运算符是一元的。因此该行不适用。

最后一行更有趣。据此,后缀增量将从“ obj++”转换为“ obj.operator++(0)”。这意味着int由于过载解析而已通过。

为完整起见,这是第13.5.7节:

  

13.5.7 [over.inc]

     

名为operator++的用户定义函数实现了前缀和后缀++运算符。如果此函数是不带参数的成员函数,或者是具有类或枚举类型的一个参数的非成员函数,则它将为该类型的对象定义前缀增量运算符++。如果函数是具有一个参数的成员函数(其类型为int)或具有两个参数的非成员函数(其中的第二个类型为int),则该函数定义后缀增量运算符++用于该类型的对象。由于使用++运算符而调用后缀增量时,int参数的值为零。


  

我之所以这样问,是因为operator+的使用方式类似于someClassObject1 + someClassObject2

+可以是一元和二进制运算符。这就是+21 + 2都是有效表达式的原因。但是++是一元运算符(即使它像二进制运算符一样重载)。