首页 > 解决方案 > 为什么 switch 和 if 语句与转换运算符的行为不同?

问题描述

为什么switchif语句与转换运算符的行为不同?

struct WrapperA
{
    explicit operator bool() { return false; }    
};

struct WrapperB
{
    explicit operator int() { return 0; }
};

int main()
{
    WrapperA wrapper_a;
    if (wrapper_a) { /** this line compiles **/ }

    WrapperB wrapper_b;
    switch (wrapper_b) { /** this line does NOT compile **/ }
}

编译错误switch quantity is not an integerif语句中被完全识别为bool. (海合会)

标签: c++if-statementswitch-statementconversion-operatorexplicit-conversion

解决方案


语法switch ( condition ) statement

条件 - 整数或枚举类型的任何表达式,或上下文 隐式可转换为整数或枚举类型的类类型,或使用大括号或等号初始化器声明此类类型的单个非数组变量。

取自cppreference。

这意味着您只能在 integer 或 enum类型上执行 switch case 。为了使编译器能够将 Wrapper 隐式转换为整数/枚举类型,您需要删除显式关键字:

显式说明符指定构造函数或转换函数(C++11 起)不允许隐式转换

您还可以将 Wrapper 转换为 int 类型。

编辑地址@acraig5075 评论:

您必须小心哪个运算符是显式的,哪个是隐式的。如果两者都是隐式的,则代码将无法编译,因为会有歧义:

struct Wrapper
{
    operator int() { return 0; }
    operator bool() { return true; }    
};

source_file.cpp:在函数“int main()”中:source_file.cpp:12:14:

错误:来自“Wrapper”的模棱两可的默认类型转换</p>

开关 (w) {

^ source_file.cpp:12:14: 注意:候选转换

包括 'Wrapper::operator int()' 和 'Wrapper::operator bool()'</p>

消除歧义的唯一方法是进行强制转换。

如果只有一个运算符是显式的,则将为 switch 语句选择另一个:

#include <iostream>
struct Wrapper
{
    explicit operator int() { return 0; }
    operator bool() { return true; }    
};

int main()
{
    Wrapper w;
    if (w) { /** this line compiles **/std::cout << " if is true " << std::endl; }
    switch (w) { 
        case 0:
            std::cout << "case 0" << std::endl;
            break;
        case 1:
            std::cout << "case 1" << std::endl;
            break;
    }
    return 0;
}

输出 :

 if is true 
case 1

w已隐式转换为1( true) (因为 operator int 是显式的)并执行 case 1。

另一方面 :

struct Wrapper
{
    operator int() { return 0; }
    explicit operator bool() { return true; }    
};

输出:

 if is true 
case 0

w已隐式转换为,0因为运算符 bool 是显式的。

在这两种情况下,if 语句都为真,因为根据上下文对 if 语句内的布尔值w进行评估。


推荐阅读