为什么对箭头(->)运算符的调用失败?

时间:2018-10-12 07:45:07

标签: c++ operator-overloading

考虑以下代码:

#include <iostream>

class Test
{
public:
    Test() : a{ 0 }
    {}

    void print() const
    {
        std::cout << "a : " << a << std::endl;
    }

    void operator->()
    {
        a = 5;
    }

    void operator++()
    {
        ++a;
    }

public:
    int a;
};

int main()
{
    Test a;
    a.print();

    // Increment operator
    a.operator++();      // CORRECT
    ++a;                 // CORRECT
    a.print();

    // Indirection operator
    a.operator->();      // CORRECT
    a->;                 // INCORRECT
    a.print();
}

为什么第二个->运算符的调用不正确?我知道->的这种用法与一般用法不同,但是标准不允许这种用法吗?

3 个答案:

答案 0 :(得分:10)

CPP标准草案(N4713)中重载的运营商中的类成员访问的小节规定:

  

16.5重载的运算符
  ...
   16.5.6类成员访问权限[over.ref]
  1. operator->应该是不带参数的非静态成员函数。它实现了使用->的类成员访问语法。

postfix-expression -> template(opt) id-expression //This!!
postfix-expression -> pseudo-destructor-name
     

如果类型为{{1}的类对象x->m(如果存在(x.operator->())->m并且如果选择了最佳运算符,则表达式x被解释为T匹配功能通过过载解析机制(16.3)。

如您所见,如果T::operator->()运算符超载,则非常需要id-expression

答案 1 :(得分:6)

Class member access [expr.ref/1] §7.6.1.5/1

  
      
  1. 后缀表达式,后跟一个点.或一个箭头->,还可以选择后面跟关键字 template ([temp.names]),后跟 id-expression 的是后缀表达式。点或箭头之前的后缀表达式;该评估的结果 id-expression 一起确定整个后缀表达式的结果
  2.   

Names [expr.prim.id] (§7.5.4)

  

id-expression:
  不合格ID
  合格ID

     
      
  1. id表达式是主表达式的受限形式。 [注意:id表达式可以出现在之后。和->运算符。 —注释]

  2.   
  3. 只能使用表示类的非静态数据成员或非静态成员函数的id表达式:

         

    2.1。作为类成员访问的一部分,其中对象表达式引用成员的类或从该类派生的类,或者
      2.2。形成指向成员([expr.unary.op])的指针,或者
      2.3。如果该id表达式表示一个非静态数据成员,并且出现在未评估的操作数中。

  4.   

答案 2 :(得分:1)

正如M.M所说,a->; sintax错误。非静态成员运算符函数参数是前缀(如operator++();后缀是operator++(int)) a.operator->();将是->a;(哇!) ,但这又是 的sintax错误。标准指定了详细信息...