【问题标题】:Direct object initialization vs Initialization with convertion functions直接对象初始化 vs 使用转换函数初始化
【发布时间】:2015-01-25 05:42:14
【问题描述】:

以下程序打印 42:

#include <iostream>

struct A
{
    operator int(){ return 42; }
};

struct B
{
    operator A(){ return A(); }
};

B b;
int a = A(b);    
int main(){ std::cout << a << std::endl; } //42

DEMO

但是如果我们尝试定义 cope/move 或同时定义这两个构造函数,它就行不通了。

#include <iostream>

struct A
{
    A(A&&){ std::cout << "A(A&&)" << std::endl; }
    A(A&){ std::cout << "A(A&)" << std::endl; }
    operator int(){ return 42; }
};

struct B
{
    operator A(){ return A(); }
};

B b;
int a = A(b);

int main(){ std::cout << a << std::endl; } //Error

DEMO

我想,描述该行为的相关部分是N4296::8.5/17.7 [dcl.init]

如果目标类型是(可能是 cv 限定的)类类型:

[...]

— 否则,如果源类型是(可能是 cv 限定的)类类型,则考虑转换函数。适用的换算 枚举函数(13.3.1.5),并选择最好的一个 通过重载决议(13.3)。用户自定义转换so 调用 selected 以将初始化表达式转换为 正在初始化的对象。如果转换无法完成或正在 模棱两可,初始化格式不正确。

它不应该取决于构造函数的缺席/存在。我们只要有合适的转换函数,就可以选择转换顺序。

【问题讨论】:

    标签: c++ class c++11


    【解决方案1】:

    您有效地删除了默认构造函数。从标准(12.1/4,强调我的):

    X默认 构造函数是类X 的构造函数,可以不带参数调用。 如果 X 类没有用户声明的构造函数,隐式声明了没有参数的构造函数 默认情况下

    IF 没有用户声明的构造函数。但是你声明了两个,所以没有隐式的默认构造函数。因此,这个:

    operator A(){ return A(); }
                      // ^^^
    

    无法编译。这就是为什么你得到的错误是

    错误:没有匹配函数调用A::A()

    代码尝试调用您的转换运算符 - 但正文无效。

    【讨论】:

    • 此外,如果您只有 A::A(A&amp;) 构造函数而不是 A::A(A&amp;&amp;) 构造函数编译仍然会失败(在添加 A::A() 构造函数之后),因为您的 B::operator A() 返回非常量右值和 A&amp; 引用不能与它绑定。重要的想法是让A 构造函数接受右值,例如。 A::A(A&amp;&amp;)A::A(const A&amp;)
    猜你喜欢
    • 2020-01-26
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 2020-02-08
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多