这条线不会编译:
Shape shape = (i % 2) ? Circle(5) : Rectangle(5, 5);
(我知道它没用,因为表达式返回的内容将简化为一个简单的Shape
,这不是重点。
无法弄清楚它为什么不能编译。我正在创建一个名为Shape
的{{1}}变量(我认为此时会创建一个新的shape
),然后我将此变量指定为表达。为什么不编译?
错误:
Shape
真正奇怪的是,具有完全相同含义的较长代码 按预期编译和运行:
no match for ternary operator
答案 0 :(得分:9)
条件运算符的详细转换规则相当复杂(如果您感兴趣,可以在this answer中找到标准的完整引用)。缺点是,当与类类型的对象一起使用时,它将尝试转换其第二个操作数以匹配第三个操作数的类型,并将其第三个操作数与第二个类型匹配,但它不会尝试将两者都转换为第三类类型。
由于Circle
无法转换为Rectangle
且Rectangle
无法转换为Circle
,编译器会抱怨(好吧,除非这两种类型定义了一些奇数转换为指针,作用域枚举或算术类型,在这种情况下§5.16[expr.cond] / p5发挥作用。)
另请注意,您的作业将对对象进行切片,probably isn't a good idea。
答案 1 :(得分:5)
条件运算符的第二个和第三个操作数必须具有公共类型,可以使用std::common_type
特征确定。有趣的是,从公共基类派生的两个类 not 将该基类作为公共类型,因此指针或引用也不相关。进一步的思考很快就表明这样的概念确实没有意义:两个类可以有任意数量的基类,一般都没有办法选择一个独特的,首选的基础。
如果要在条件运算符中使用派生类,则必须自己明确地转换类型。
您的代码的更现实和明智的例子将是这样的:
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";
答案 2 :(得分:2)
当条件运算符中两个分支的类型类型不同时,根据5.16 [expr.cond]第16段,需要将其转换为另一个:
否则,如果第二个和第三个操作数具有不同的类型并且具有(可能是cv限定的)类类型,或者两者都是相同值类别的glvalues和除cv-qualification之外的相同类型,则尝试将每个操作数转换为另一个操作数的类型。 ...
其他涉及的案例不适用:它们是void
类型或一个throw
表达式的分支。遗漏只是解释了如何尝试转换以及选择转换的情况(实际上,如果一个表达式的类型唯一地转换为另一个而不是相反的转换)。
假设您的Circle
或Rectangle
可转换为Shape
,您可以将一个或两个表达式明确转换为Shape
。