【问题标题】:Why Doesn't This Do an Implicit Cast to the Converting Constructor?为什么这不对转换构造函数进行隐式转换?
【发布时间】:2018-10-29 02:23:01
【问题描述】:

所以我有这个代码:

struct Foo {
    Foo() { cout << "default\n"; }
    Foo(const long long) { cout << "implicit\n"; }
};

struct Bar {
    Bar(const short param) : param(param) {}
    operator long long() const { return static_cast<long long>(param); }
    const short param;
};

我原以为Foo foo = Bar(13) 会使用我的隐式强制转换,然后使用转换构造函数。 But it errors:

错误:从 Bar 转换为非标量类型 Foo 请求

这很好用:Foo foo(Bar(13))。为什么我的隐式转换用于显式转换构造,而不用于隐式转换构造?

我从https://en.cppreference.com/w/cpp/language/copy_initialization得到的规则说:

转换的结果,如果使用转换构造函数,则为纯右值表达式,然后用于直接初始化对象

【问题讨论】:

  • 不存在“隐式强制转换”之类的东西。强制转换是一种显式转换。
  • 是否可以将转换构造函数和强制转换运算符都视为隐式转换?我想区分。
  • 没关系,因为无论哪种方式都没有“隐式强制转换”之类的东西,但您已经使用了 3 次这个词。
  • @LightnessRacesinOrbit 隐式转换会被认为是正确的吗?
  • 如果这就是你的意思。我不知道,因为你使用了一个不存在的术语!

标签: c++ constructor implicit-conversion typecast-operator explicit-conversion


【解决方案1】:

首先从Barlong long的隐式转换,从long longFoo的隐式转换都是用户定义的转换。

Foo foo = Bar(13); 执行copy initialization,编译器会尝试将Bar 隐式转换为Foo。需要进行两次隐式转换,即将Bar 转换为long long,然后将long long 转换为Foo。但在一个implicit conversion 序列中只允许进行一次用户自定义转换。

隐式转换序列按以下顺序由以下组成:

1) 零个或一个标准转换序列;

2) 零次或一次用户自定义转换;

3) 零个或一个标准转换序列。

用户定义的转换由零个或一个非显式单参数构造函数或非显式转换函数调用组成

Foo foo(Bar(13)); 执行direct initialization。将检查Foo 的构造函数,并通过重载决议选择最佳匹配。只需要一个隐式的用户定义转换(从Barlong long);之后调用Foo::Foo(long long) 直接构造foo

【讨论】:

  • 那么显式转换允许更多的转换?因为必须进行 2 次转换(如果我们正在考虑将转换构造函数转换为一次转换。)
  • @JonathanMee 所以在显式转换中允许更多的转换当然,如果你显式地做,你可以指定任意数量的转换。
  • Foo foo(Bar(13)) 中只有一次隐式转换,从Barlong long。但是Foo foo = Bar(13) 需要将Bar 转换为long long,然后再转换为Foo,以便foo 可以被复制构造。
  • @JonathanMee 答案已修改。
【解决方案2】:

当你使用复制初始化然后根据documentation

此外,复制初始化中的隐式转换必须直接从初始化器生成 T,而例如直接初始化需要从初始化程序隐式转换为 T 的构造函数的参数。

重点是我的。事实并非如此。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 2013-11-02
    • 2020-06-20
    • 2021-12-04
    • 2019-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多