考虑以下代码:
#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();
}
为什么第二个->
运算符的调用不正确?我知道->
的这种用法与一般用法不同,但是标准不允许这种用法吗?
答案 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:
- 后缀表达式,后跟一个点
.
或一个箭头->
,还可以选择后面跟关键字 template ([temp.names]),后跟 id-expression 的是后缀表达式。点或箭头之前的后缀表达式;该评估的结果与 id-expression 一起确定整个后缀表达式的结果。
Names [expr.prim.id] (§7.5.4):
id-expression:
不合格ID
合格ID
id表达式是主表达式的受限形式。 [注意:id表达式可以出现在之后。和->运算符。 —注释]
只能使用表示类的非静态数据成员或非静态成员函数的id表达式:
2.1。作为类成员访问的一部分,其中对象表达式引用成员的类或从该类派生的类,或者
2.2。形成指向成员([expr.unary.op])的指针,或者
2.3。如果该id表达式表示一个非静态数据成员,并且出现在未评估的操作数中。
答案 2 :(得分:1)
正如M.M所说,a->;
是 sintax错误。非静态成员运算符函数无参数是前缀(如operator++()
;后缀是operator++(int))
a.operator->();
将是->a;
(哇!) ,但这又是 的sintax错误。标准指定了详细信息...