为什么我不能在这里使用三元运算符?

Avi*_*ohn 4 c++ variables expression variable-assignment

这行不会编译:

Shape shape = (i % 2) ? Circle(5) : Rectangle(5, 5);
Run Code Online (Sandbox Code Playgroud)

(我知道它没用,因为表达式返回的内容将简化为简单Shape,这不是重点).

无法弄清楚为什么它不会编译.我正在创建一个Shape名为的变量shape(我认为此时会创建一个新Shape变量),然后我将此变量赋给表达式的结果.为什么不编译?

错误:

no match for ternary operator
Run Code Online (Sandbox Code Playgroud)

什么是真正奇怪的是,有完全相同的含义较长的代码编译和运行按预期:

    Shape shape;
    if (i % 2)
        shape = Rectangle(5, 5);
    else
        shape = Circle(5);
Run Code Online (Sandbox Code Playgroud)

T.C*_*.C. 9

条件运算符的详细转换规则相当复杂(如果您感兴趣,可以在此答案中找到标准的完整引用).缺点是,当与类类型的对象一起使用时,它将尝试转换其第二个操作数以匹配第三个操作数的类型,并将其第三个操作数与第二个类型相匹配,但它不会尝试将两者都转换为第三类类型.

由于Circle不可转换为RectangleRectangle不可转换Circle,编译器会抱怨(好吧,除非这两种类型定义了一些奇怪的转换为指针,作用域枚举或算术类型,在这种情况下§5.16[expr.cond]/p5来了发挥).

另请注意,您的赋值将对对象进行切片,这可能不是一个好主意.

  • @AvivCohn:在Java中,您处理对象的引用,而不是对象. (4认同)
  • @AvivCohn Java既没有多重继承,也没有复制语义.C++要复杂得多. (2认同)

Ker*_* SB 6

条件运算符的第二个和第三个操作数必须具有公共类型,可以使用std::common_type特征确定.有趣的是,从公共基类派生的两个类具有该基类作为公共类型,因此指针或引用也不相关.进一步的思考很快就表明,这样的概念确实没有意义:两个类可以有任意数量的基类,并且通常无法选择唯一的首选基类.

如果要在条件运算符中使用派生类,则必须自己明确地转换类型.

代码的一个更现实和明智的例子是这样的:

Shape const & s = ask_user() ? static_cast<Shape const &>(show_me_a_circle())
                             : static_cast<Shape const &>(squares_all_the_way());

std::cout << "Your shape is " << s.get_colour() << ".\n";
Run Code Online (Sandbox Code Playgroud)

  • 这是一种重言式......`common_type`是使用条件运算符定义的. (2认同)