【问题标题】:why can I not use the dummy parameter in postfix operator++ like someClassObject++5?为什么我不能像 someClassObject++5 那样在后缀 operator++ 中使用虚拟参数?
【发布时间】:2019-06-04 08:29:38
【问题描述】:

我知道我可以在后缀运算符 ++ 中使用虚拟 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 会以相同的方式工作。

【问题讨论】:

  • 后缀++(和--)的参数是一个hack(或聪明的解决方法,取决于你的观点),它被引入只是为了允许前缀和后缀的重载运营商。你不应该将它用于任何事情。
  • 我的猜测是,现在,如果重新设计是可能的,那么它将通过标签类型参数而不是不明显的 int 重载来区分,例如重载MyClass&amp; operator++(std::prefix_t)MyClass operator++(std::postfix_t)

标签: c++ operator-overloading


【解决方案1】:

由于最大咀嚼规则,表达式

t1++x

解析

t1 ++ x

分组

(t1 ++) x

这毫无意义;而喜欢t1 x 是没有意义的。

【讨论】:

  • 感谢您回答问题。你的回答很有道理。我会研究什么是最大咀嚼规则。
【解决方案2】:

我知道我可以在后缀 operator++ 中使用虚拟 int 作为 someClassObject.operator++(5),但为什么不能像 someClassObject++5 那样使用它?

Because the Standard Says 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)) 是声明,因此此特定条款适用于您的情况。

首先,我将第 13.5.2 条包含在行中以消除任何疑问。 §13.5.2 处理二元运算符。但正如我们已经确定的,C++ 中没有二元 ++ 运算符,唯一的后缀 ++ 运算符是一元运算符。所以该行不适用。

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

为了完整起见,这里是 §13.5.7:

13.5.7 [over.inc]

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


我问这个是因为operator+ 可以像someClassObject1 + someClassObject2 一样使用。

+ 既可以是一元运算符,也可以是二元运算符。这就是为什么+21 + 2 都是有效表达式的原因。但是++ 是一元运算符(尽管它像二元运算符一样重载)。

【讨论】:

    猜你喜欢
    • 2011-01-23
    • 1970-01-01
    • 1970-01-01
    • 2017-11-25
    • 1970-01-01
    • 1970-01-01
    • 2012-01-06
    • 1970-01-01
    • 2011-03-06
    相关资源
    最近更新 更多