首页 文章

使用三元条件运算符时,不兼容的操作数类型

提问于
浏览
16

这段代码:

bool contains = std::find(indexes.begin(), indexes.end(), i) != indexes.end();
  CardAbility* cardAbility = contains ? new CardAbilityBurn(i) : new CardAbilityEmpty;

给我以下错误:

不兼容的操作数类型CardAbilityBurn和CardAbilityEmpty

但是,如果我写这样的代码:

if (contains)
 {
    cardAbility = new CardAbilityBurn(i);
 }
 else
 {
    cardAbility = new CardAbilityEmpty;
 }

然后编译器不介意 . 为什么这样?我想使用三元条件运算符,因为它只是一行 . 那有什么不对?

我需要注意(我认为你可能需要这些信息) CardAbilityEmptyCardAbilityBurn 都来自 CardAbility 所以他们这么说兄弟 .

谢谢

2 回答

  • 2

    C 's type system determines expressions'类型由里到外[1] . 这意味着条件表达式的类型是在分配给 CardAbility* 之前确定的,并且编译器必须只选择 CardAbilityBurn*CardAbilityEmpty* .

    由于C具有多重继承和一些可能的转换路径,因为没有一个类型是另一个类型的超类,编译就会停止 .

    要成功编译,您需要提供缺少的部分:将一个或两个操作数强制转换为基类类型,因此条件表达式作为一个整体可以采用该类型 .

    auto* cardAbility = contains
        ? static_cast<CardAbility*>(new CardAbilityBurn(i))
        : static_cast<CardAbility*>(new CardAbilityEmpty  );
    

    (注意使用auto,因为您已经在右侧表达式中提供了目标类型 . )

    然而,它有点复杂,所以最终 if - else 结构在这种情况下更适合 .

    [1]有一个例外:重载函数名称在将它们(隐式或显式)转换为其中一个版本之前没有确定类型 .

  • 16

    several cases described for Microsoft compilers,如何处理操作数类型 .

    如果两个操作数的类型相同,则结果属于该类型 . 如果两个操作数都是算术类型或枚举类型,则执行通常的算术转换(在算术转换中涵盖)以将它们转换为公共类型 . 如果两个操作数都是指针类型或者如果一个是指针类型而另一个是一个计算结果为0的常量表达式,则执行指针转换以将它们转换为公共类型 . 如果两个操作数都是引用类型,则执行引用转换以将它们转换为公共类型 . 如果两个操作数都是void类型,则常见类型为void类型 . 如果两个操作数具有相同的用户定义类型,则公共类型是该类型 . 如果操作数具有不同的类型并且至少一个操作数具有用户定义的类型,则语言规则用于确定公共类型 . (见下面的警告 . )

    然后有一个警告:

    如果第二个和第三个操作数的类型不相同,则调用C标准中指定的复杂类型转换规则 . 这些转换可能会导致意外行为,包括临时对象的构造和破坏 . 因此,我们强烈建议您(1)避免将用户定义的类型用作条件运算符的操作数,或者(2)如果使用用户定义的类型,则将每个操作数显式地转换为公共类型 .

    也许这就是原因,Apple在LLVM中停用了这种隐式转换 .

    所以,如果/ else似乎更适合你的情况 .

相关问题