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

ua4mk5z4  于 2023-01-15  发布在  其他
关注(0)|答案(3)|浏览(172)

此行无法编译:

Shape shape = (i % 2) ? Circle(5) : Rectangle(5, 5);

(我知道这是无用的,因为无论表达式返回什么,都将被简化为简单的Shape,这不是重点)。
不知道为什么它不能编译,我创建了一个名为shapeShape变量(我认为这会创建一个新的Shape),然后我给这个变量赋值一个表达式的结果,为什么这个不能编译?
错误:

no match for ternary operator

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

Shape shape;
if (i % 2)
     shape = Rectangle(5, 5);
else shape = Circle(5);
b5buobof

b5buobof1#

条件运算符的详细转换规则相当复杂(如果你有兴趣,你可以在这个答案中找到标准的完整引用)。简短的说,当与类类型的对象一起使用时,它将试图转换它的第二个操作数以匹配第三个的类型,并转换它的第三个操作数以匹配第二个的类型,但它不会尝试将两者都转换为第三类类型。
由于Circle不能转换成RectangleRectangle也不能转换成Circle,编译器会抱怨(除非这两种类型定义了一些奇怪的转换,转换成指针、作用域枚举或算术类型,在这种情况下§5.16 [expr.cond]/p5会起作用)。
还请注意,您的赋值将对对象进行切片,即probably isn't a good idea

i34xakig

i34xakig2#

条件运算符的第二个和第三个操作数必须具有 common type,这可以通过std::common_type trait来确定。有趣的是,从一个公共基类派生的两个类 * 不 * 将该基类作为公共类型,指针或引用也不具有这样的相关性。进一步的思考很快表明,这样的概念确实没有意义:两个类可以具有任意数量的共同基类,并且通常没有办法选择唯一的优选基类。
如果要在条件运算符中使用派生类,则必须自己显式地强制转换类型。
一个更实际、更合理的代码示例如下所示:

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";
pcww981p

pcww981p3#

当条件运算符中两个分支的类型不同时,需要根据5.16 [expr.cond]第16段将一个分支转换为另一个分支:
否则,如果第二个和第三个操作数具有不同的类型,并且其中一个具有(可能是cv限定的)类类型,或者如果两者都是相同值类别的glvalue,并且除了cv限定之外具有相同的类型,则尝试将这些操作数中的每一个转换为另一个的类型。
所提到的其他情况不适用:它们是关于类型是void或一个分支是throw表达式的。省略只是解释了如何尝试转换以及在哪些情况下选择转换(本质上,如果一个表达式的类型唯一地转换为另一个,而不是相反)。
假设您的CircleRectangle可转换为Shape,您可以显式地将一个或两个表达式转换为Shape

相关问题