否定运算符和比较

时间:2012-11-13 12:19:12

标签: c++ comparison negation

让我们拿一些代码示例:

! 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>
  1. 第一次通话(控制通话)非常清楚。我们检查是否需要运营商。
  2. 第二次电话会议证明了我先说的内容。首先调用否定运算符,而不是结果(bool)运算符&gt;被称为。
  3. 第三次电话是困扰我的。
  4. 这里提出我的问题。为什么SomeObjInstance > 0来电与SomeObjInstance.operator>(0)不同。我知道以第二种方式(作为成员)呼叫运营商并不常见,但为什么这种呼叫有所不同?如果成员运算符不存在,我总是认为SomeObjInstance > 0被翻译成成员调用SomeObjInstance.operator>(0)或函数调用bool operator>(const Test &, int)

    在C ++标准中描述了这种行为,或者这可能是某种未定义的行为?

3 个答案:

答案 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>)())