三元运算符隐式转换为基类
考虑这段代码:
struct Base
{
int x;
};
struct Bar : Base
{
int y;
};
struct Foo : Base
{
int z;
};
Bar* bar = new Bar;
Foo* foo = new Foo;
Base* returnBase()
{
Base* obj = !bar ? foo : bar;
return obj;
}
int main() {
returnBase();
return 0;
}
这在Clang或GCC下不起作用,给我:
This doesn't work under Clang or GCC, giving me :
错误:不同指针类型'Foo *'
和'Bar *'之间的条件表达式缺少强制转换的Base * obj =!bar? foo:bar;
error: conditional expression between distinct pointer types ‘Foo*’ and ‘Bar*’ lacks a cast Base* obj = !bar ? foo : bar;
这意味着要编译,我必须将代码更改为:
Which means for it to compile I have to change the code to :
Base* obj = !bar ? static_cast<Base*>(foo) : bar;
因为隐式强制转换为 Base *
存在,是什么阻止了编译器这样做?
Since an implicit cast to a Base*
exists, what is preventing the compiler from doing so?
换句话说,为什么 Base * obj = foo;
无需强制转换但可以使用?:
运算符来工作吗?是因为不清楚我是否要使用 Base
部分?
In other words, why does Base* obj = foo;
work without a cast but using the ?:
operator doesn't? Is it because it's not clear that I want to use the Base
part?
引用C ++标准草案N4296第5.16节有条件的运算符 第6.3段:
Quoting from C++ standard draft N4296, Section 5.16 Conditional operator, Paragraph 6.3:
- 第二和第三操作数中的一个或两个具有指针类型;进行了指针转换(4.10)和
资格转换(4.4) ,以将其转换为复合指针类型(第5条)。
结果是复合指针类型。
- One or both of the second and third operands have pointer type; pointer conversions (4.10) and qualification conversions (4.4) are performed to bring them to their composite pointer type (Clause 5). The result is of the composite pointer type.
第5节表达式,第13.8和13.9段:
Section 5 Expressions, Paragraph 13.8 and 13.9:
两个分别具有T1和T2类型的操作数p1和p2的复合指针类型,在
处,至少有一个是指向成员类型或std :: nullptr_t的指针或指针,是:
The composite pointer type of two operands p1 and p2 having types T1 and T2, respectively, where at least one is a pointer or pointer to member type or std::nullptr_t, is:
- 如果T1和T2是类似的类型(4.4),T1和T2的cv组合类型;
- 否则,需要确定复合指针类型的程序格式错误。
- if T1 and T2 are similar types (4.4), the cv-combined type of T1 and T2;
- otherwise, a program that necessitates the determination of a composite pointer type is ill-formed.
注意:我在这里复制5 / 13.8只是为了向您展示它没有打。实际上是5 / 13.9,程序格式错误。
Note: I copied 5/13.8 here just to show you that it doesn't hit. What's actually in effect is 5/13.9, "the program is ill-formed".
第4.10节指针转换,第3段:
And Section 4.10 Pointer conversions, Paragraph 3:
类型为 pointer to cv D的prvalue(其中D是类类型)可以转换为类型为 pointer $的prvalue b $ b到Cv B,其中B是D的基类(第10条)。如果B是D的不可访问(第11条)或模棱两可(10.2)
,则该程序需要进行此转换格式不正确。转换的结果是指向派生类对象的基类子对象的
指针。空指针值将转换为目标类型的
空指针值。
A prvalue of type "pointer to cv D", where D is a class type, can be converted to a prvalue of type "pointer to cv B", where B is a base class (Clause 10) of D. If B is an inaccessible (Clause 11) or ambiguous (10.2) base class of D, a program that necessitates this conversion is ill-formed. The result of the conversion is a pointer to the base class subobject of the derived class object. The null pointer value is converted to the null pointer value of the destination type.
因此,没关系(完全)Foo和Bar都源自一个相同的基类。唯一重要的是,指向Foo的指针和指向Bar的指针不能相互转换(没有继承关系)。
So, it doesn't matter (at all) that both Foo and Bar are derived from one same base class. It only matters that a pointer to Foo and a pointer to Bar are not convertible to each other (no inheritance relationship).