c++ - 三元运算符隐式转换为基类

标签 c++ language-lawyer c++17 ternary-operator implicit-conversion

考虑这段代码:

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 下不起作用,给我:

error: conditional expression between distinct pointer types ‘Foo*’ and ‘Bar*’ lacks a cast Base* obj = !bar ? foo : bar;



这意味着要编译我必须将代码更改为:
Base* obj = !bar ? static_cast<Base*>(foo) : bar;

由于隐式转换为 Base*存在,是什么阻止编译器这样做?

换句话说,为什么Base* obj = foo;无需类型转换即可工作,但使用 ?:运营商没有?是不是因为不清楚我要使用Base部分?

最佳答案

引自 C++ 标准草案 N4296,第 5.16 节条件运算符,第 6.3 段:

  • 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 段:

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:

  • 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,“程序格式错误”。

以及第 4.10 节指针转换,第 3 段:

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 的指针不可相互转换(没有继承关系)。

关于c++ - 三元运算符隐式转换为基类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62790856/

相关文章:

c - 当什么都不执行时,是否有可以使用的虚拟左值?

c++ - 动态可转换类型特征

c++ - 为什么返回类型推导不能支持带有 std::is_invocable_v 的 SFINAE

c++ - 我的 SFML/C++ 程序按预期工作,但如何使移动变慢?

c++ - 是否使用了 posix 命名空间?

c++ - 如果我将变量重新定义为 auto,并且推导的类型相同,它是否格式正确?

c++ - 如何使用类模板特化创建别名模板的特化?

c++ - 如何按值返回 "auto"返回类型函数

c++ - 从 Objective-C 移植到 C++ 的最佳方式是什么?

C++ : Initializing base class constant static variable with different value in derived class?