让我们拿一些代码示例:
! 4 > 0;
从C ++标准我们知道,否则将首先进行否定,而不是比较。但是,如果我们稍微扩展这个例子:
#include <iostream>
class Test
{
public:
bool operator!() const
{
std::cout << "operator!" << std::endl;
return false;
}
bool operator>(const int &) const
{
std::cout << "operator>" << std::endl;
return false;
}
};
int main(int argc, char * argv[])
{
Test t;
std::cout << "t > 0;" << std::endl;
t > 0;
std::cout << "! t > 0;" << std::endl;
! t > 0;
std::cout << "!t.operator>(0)" << std::endl;
! t.operator>(0);
return 0;
}
该计划的输出将是:
t > 0;
operator>
! t > 0;
operator!
!t.operator>(0)
operator>
这里提出我的问题。为什么SomeObjInstance > 0
来电与SomeObjInstance.operator>(0)
不同。我知道以第二种方式(作为成员)呼叫运营商并不常见,但为什么这种呼叫有所不同?如果成员运算符不存在,我总是认为SomeObjInstance > 0
被翻译成成员调用SomeObjInstance.operator>(0)
或函数调用bool operator>(const Test &, int)
。
在C ++标准中描述了这种行为,或者这可能是某种未定义的行为?
答案 0 :(得分:6)
成员访问运算符.*
的优先级高于否定运算符!
。
在C ++标准中描述了这种行为,或者这可能是某种未定义的行为?
这很可能是相关段落:
13.5重载运算符[over.oper]
5)通常不直接调用操作员函数;相反,它们被调用来评估它们实现的运算符(13.5.1 - 13.5.7)。但是,可以使用operator-function-id作为函数调用语法(5.2.2)中函数的名称来显式调用它们。
在您的第一个示例t > 0;
中,它将使用具有关系比较运算符优先级的相应运算符。但是,在您的第二个版本t.operator>(0)
中,您将其用作函数调用。因此,Test::operator>
被用作成员函数,这将导致您描述的行为,因为它失去了它的运算符特性(“它们可以被显式调用,但是,使用operator-function-id作为函数调用语法“”中函数的名称。
另见:
答案 1 :(得分:2)
请戴上你的编译器帽子片刻。您需要根据一组明确的规则(包括运算符优先级)来解析和计算表达式。评估涉及调用成员函数(operator>()
)的事实,如果表达式使用运算符>
,也会调用它 - 那么什么?您是否想要特殊情况并假设在这种情况下应该更改默认优先级?你准备好了多远?例如。如果间接调用此方法,还是通过函数指针调用?我认为它会使编译器的逻辑变得复杂,并且仍然允许反直觉的例子,类似于你原来的问题。
答案 2 :(得分:1)
.
和()
的优先级高于!
。运算符语法被解析为
(!t) > 0;
而显式调用被解析为
!((t.operator>)())