【问题标题】:Negation operator and comparison否定运算符和比较
【发布时间】:2012-11-13 12:19:11
【问题描述】:

让我们来一些代码示例:

! 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. 第二次调用是我第一次陈述的证明。首先调用否定运算符,然后调用结果(布尔)运算符>。
  3. 第三个电话让我很困扰。

这里提出了我的问题。为什么SomeObjInstance &gt; 0 调用与SomeObjInstance.operator&gt;(0) 不同。我知道以第二种方式(作为成员)调用操作员并不常见,但为什么这种调用不同?我总是认为SomeObjInstance &gt; 0 被翻译成成员调用SomeObjInstance.operator&gt;(0) 或函数调用bool operator&gt;(const Test &amp;, int) 如果成员运算符不存在。

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

【问题讨论】:

    标签: c++ comparison negation


    【解决方案1】:

    成员访问运算符.* 的优先级高于否定运算符!。

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

    这很可能是相关段落:

    13.5 重载运算符 [over.oper]

    5) 通常不直接调用操作符函数;相反,它们被调用来评估它们实现的运算符 (13.5.1 – 13.5.7)。但是,可以使用 operator-function-id 作为函数调用语法 (5.2.2) 中的函数名称来显式调用它们。

    在您的第一个示例t &gt; 0; 中,它将使用具有优先级的相应运算符作为关系比较运算符。但是,在您的第二个版本t.operator&gt;(0) 中,您将其用作函数调用。因此,Test::operator&gt; 被用作成员函数,这将导致您描述的行为,因为它失去了它的操作符特性(“它们可以被显式调用,但是,使用 operator-function-id 作为函数调用语法中的函数").

    另见:

    【讨论】:

    • 这是微不足道的,显然是 OP 知道的。它没有回答所提出的问题。
    • 感谢您详细解答。
    • @KamilKlimek:不客气。我仍然不确定是否有任何其他段落可以更好地描述这种行为,但我无法找到其他内容。
    【解决方案2】:

    戴上你的编译器帽一会儿。您需要根据一组明确的规则(包括运算符优先级)解析和评估表达式。评估涉及调用成员函数 (operator&gt;()) 的事实,如果表达式使用运算符 &gt;,也会调用该成员函数 - 那又如何?您是否想创建一个特殊情况并假设在这种情况下应该更改默认优先级?你准备走多远?例如。如果此方法是间接调用的,还是由函数指针调用的?我认为这会使编译器的逻辑复杂化,并且仍然允许违反直觉的示例,类似于您的原始问题。

    【讨论】:

      【解决方案3】:

      . 和 () 的优先级高于 !。运算符语法被解析为

      (!t) > 0;
      

      而显式调用被解析为

      !((t.operator>)())
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多