问题 不允许对自定义类型进行多次隐式转换?


class C {
public:
    C() { }
};

class B {
public:
    B(C c) { }
    B() { }
};

class A {
public:
    A(bool b) { }
    A(B b) { }
};

int main() {
    A a1 = true; // bool -> A        is allowed
    A a2 = B();  // B -> A           is allowed

    A a3 = 7;    // int -> bool -> A is allowed
    A a4 = C();  // C -> B -> A      isn't allowed
}

为什么我可以使用两步隐式转换 bool 但不能用它 C? 描述多步隐式转换的一般规则是什么?


2626
2017-10-11 19:43


起源



答案:


没有多步骤 用户自定义 隐式转换。

int -> bool -> A

是允许的,因为 int->bool 转换不是用户定义的。

12.3转换[class.conv]

1类对象的类型转换可以由构造函数指定   并通过转换功能。这些转换称为用户定义   转换并用于隐式类型转换(第4节)   初始化(8.5),以及显式类型转换(5.4,5.2.9)。

2用户定义的转换仅在明确无误的情况下应用   (10.2,12.3.2)。转换遵守访问控制规则(第11条)。   模糊度解决(3.4)后应用访问控制。

3 [注:   有关在函数调用中使用转换的讨论,请参见13.3   以及下面的例子。 - 尾注]

4最多一个用户定义的   隐式应用转换(构造函数或转换函数)   到一个单一的价值。


10
2017-10-11 19:44



因此,除了以外没有其他基本定义的转换 int->bool? - Jofsey
@Lescott有很多内置的转换/促销活动。 int->bool 就是你在这个特殊情况下所拥有的。 - Luchian Grigore


答案:


没有多步骤 用户自定义 隐式转换。

int -> bool -> A

是允许的,因为 int->bool 转换不是用户定义的。

12.3转换[class.conv]

1类对象的类型转换可以由构造函数指定   并通过转换功能。这些转换称为用户定义   转换并用于隐式类型转换(第4节)   初始化(8.5),以及显式类型转换(5.4,5.2.9)。

2用户定义的转换仅在明确无误的情况下应用   (10.2,12.3.2)。转换遵守访问控制规则(第11条)。   模糊度解决(3.4)后应用访问控制。

3 [注:   有关在函数调用中使用转换的讨论,请参见13.3   以及下面的例子。 - 尾注]

4最多一个用户定义的   隐式应用转换(构造函数或转换函数)   到一个单一的价值。


10
2017-10-11 19:44



因此,除了以外没有其他基本定义的转换 int->bool? - Jofsey
@Lescott有很多内置的转换/促销活动。 int->bool 就是你在这个特殊情况下所拥有的。 - Luchian Grigore


由于这种结构完全合法

A a4((C()));

问题是,你使用复制启动。真的,你的例子等于

A a4((A(C()));

8.5 / 16

初始化器的语义如下。目标类型是对象或引用的类型 初始化,源类型是初始化表达式的类型。如果初始化程序不是单个(可能是 括号内的表达式,未定义源类型。

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

- 否则(即,对于剩余的复制初始化情况),用户定义的转换序列 可以从源类型转换为目标类型或(转换函数时) (如果使用)对其派生类进行枚举,如13.3.1.4所述,最好的是 通过重载决议选择(13.3)。

13.3.1.4/1

在8.5中指定的条件下,作为类类型对象的复制初始化的一部分,由用户定义 可以调用转换以将初始化表达式转换为要初始化的对象的类型。

重载分辨率用于选择要调用的用户定义的转换。假设“cv1 T”是 要初始化的对象的类型,使用T类类型,候选函数选择如下: - T的转换构造函数(12.3.1)是候选函数。

- 当初始化表达式的类型是类类型“cv S”时,非显式转换函数 考虑S及其基类。

13.3.3.1/4

但是,在考虑构造函数或用户定义的转换函数的参数时 当在类的第二步中复制/移动临时时,调用13.3.1.3的候选者 复制初始化,通过13.3.1.7将初始化列表作为单个参数或初始化程序传递时 list只有一个元素,并且转换为某个类X或引用(可能是cv-qualified)X是 考虑X的构造函数的第一个参数,或者 13.3.1.4在所有情况下,13.3.1.5或13.3.1.6, 只要 考虑标准转换序列和省略号转换序列。

在这种情况下,不考虑用户定义的转换(C - > B)。


1
2017-10-11 21:08