2017-09-26 351 views
3

我虽然对运算符重载,并配备了一个有趣的代码:逻辑运算符的执行顺序

#include <iostream> 

class A { 
public: 
    operator bool() { 
     return true; 
    } 

    bool operator!() { 
     return false; 
    } 
}; 

int main() { 
    A a; 

    if (!a) { 
     std::cout << "HELLO"; 
    } else { 
     std::cout << "WORLD"; 
    } 
    std::cout << std::endl; 

    return 0; 
} 

什么将被称为第一,之后是什么?为什么?这在cppreference的任何地方都有描述吗?

P.S.对于downvoters和其他谁认为我不能自己执行此代码。我可以。我做到了。我已经多次改变它来看它的行为。所以呢?这不是一个解释。我已经要求参考哪个明确说明什么规则这个代码服从。它在我的机器上的工作方式并不能回答这个问题 - 如果这种方式在不同的环境(操作系统,可能是处理器等)中甚至不可移植?

+1

您是否尝试过? https://ideone.com/sW8yEm – mch

+2

没有什么会被称为第一次和之后。只调用'operator!'。 – StoryTeller

+0

@mch是我已经尝试过,但我无法解释它是如何工作的。 –

回答

7

工作原理很简单图谋后者。编译器解析源代码并看到if(!a)。然后它检查A是否定义了operator!。碰巧它发生了。所以被调用。

如果它已经看到if(a)它将检查A是否可以转换为可以在if的条件下使用的东西。恰恰相反,它确实是可以兑换的。

如果没有operator!,则编译器会检查是否可以将A转换为可能在逻辑上取反的东西。 然后转换到布尔应该已经执行。


顺便说一句,转换即使在令人惊讶的地方也会发生。例如a + 1将被编译。我想,不是我们想要的。最好仅在预期内容为bool时才允许它。您可以通过将转换运算符标记为:

explicit operator bool() { 
    return true; 
} 
4

!a不过是您定义的a.operator!()的语法糖:这是编译器的首选选项。

所以转换为bool运营商从来不是一个候选人。

您可以通过编写

if (!(bool)a) {