Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
因为在C++;当存在两种相同转换的可能性时,它们如何相互作用? 我只是想澄清C++是如何工作的,这不是真正的解决我的代码中的一个特殊问题。 在C++中,你可以说类型A应该用两种不同的方式隐式转换为B。_C++_Implicit Conversion_Conversion Operator - Fatal编程技术网

因为在C++;当存在两种相同转换的可能性时,它们如何相互作用? 我只是想澄清C++是如何工作的,这不是真正的解决我的代码中的一个特殊问题。 在C++中,你可以说类型A应该用两种不同的方式隐式转换为B。

因为在C++;当存在两种相同转换的可能性时,它们如何相互作用? 我只是想澄清C++是如何工作的,这不是真正的解决我的代码中的一个特殊问题。 在C++中,你可以说类型A应该用两种不同的方式隐式转换为B。,c++,implicit-conversion,conversion-operator,C++,Implicit Conversion,Conversion Operator,如果您是A的作者,您可以在A中添加以下内容: operator B() { // code } 如果您是B的作者,您可以在B中添加类似的内容: B(const A &a) { // code } 如果我理解正确的话,其中任何一个都将允许A隐式转换为B。那么,如果两者都被定义,那么使用哪一个呢?这是允许的吗 注意:我理解你可能永远不会处于这样的情况。您可以使构造函数显式,或者更可能只有两个构造函数中的一个。我只是想知道C++规范是什么,我不知道如何去查看。< /P> [C

如果您是A的作者,您可以在A中添加以下内容:

operator B() {
   // code
}
如果您是B的作者,您可以在B中添加类似的内容:

B(const A &a) {
    // code
}
如果我理解正确的话,其中任何一个都将允许A隐式转换为B。那么,如果两者都被定义,那么使用哪一个呢?这是允许的吗

注意:我理解你可能永远不会处于这样的情况。您可以使构造函数显式,或者更可能只有两个构造函数中的一个。我只是想知道C++规范是什么,我不知道如何去查看。< /P>
[C++11:12.3/2]:
用户定义的转换仅在明确的地方应用。[……]


12.3接着列出您确定的两种类型。

不幸的是,这个问题的答案可能比您想要的更复杂。诚然,编译器会拒绝不明确的转换,正如轨道上的亮度竞赛所指出的那样,但是这些转换是不明确的吗?让我们看几个案例。所有参考都是C++11标准

显式转换 这并不能直接回答你的问题,因为你问的是隐式转换,但既然轨道上的亮度竞赛给出了显式转换的例子,我还是要讨论一下

在以下情况下,将执行从
A
B
的显式转换:

  • 您使用语法
    (B)a
    ,其中
    a
    a
    类型,在这种情况下相当于
    static\u cast(a)
    (C++11标准,§5.4/4)
  • 您使用静态转换,在本例中,它将创建一个临时转换,该转换以与声明
    bt(a)相同的方式初始化初始化
    t
    ;(§5.2.9/4)
  • 您使用的语法是
    B(a)
    ,它相当于
    (B)a
    ,因此也执行与声明
    bt(a)中的初始化相同的操作(§5.2.3/1)
因此,在每种情况下,使用
a
类型的值作为参数,对
B
类型的prvalue执行直接初始化。§8.5/16规定只考虑构造函数,因此将调用
B::B(const A&)
。(更多细节,请参见我的回答:)

复制初始化 在复制初始化中

B b = a;
B b = {a};
类型为
a
的值
a
首先使用用户定义的转换序列(隐式转换序列)转换为类型为
B
的临时值。然后,此临时命令用于直接初始化
b

因为这是由不同类类型的对象对类类型的复制初始化,所以转换构造函数
B::B(const a&)
和转换函数
a::operator B()
都是转换的候选对象(§13.3.1.4)。之所以称后者,是因为它赢得了重载解析。请注意,如果
B::B
具有参数
A&
而不是
const A&
,则重载将是不明确的,程序将无法编译。有关本标准的详细信息和参考信息,请参见以下答案:

复制列表初始化 复制列表初始化

B b = a;
B b = {a};
只考虑
B
(§8.5.4/3)的构造函数,而不考虑
A
的转换函数,因此将调用
B::B(const A&)
,就像在显式转换中一样

函数参数的隐式转换 如果我们有

void f(B b);
A a;
f(a);
然后,编译器必须选择最佳隐式转换序列,将
a
转换为
B
类型,以便将其传递给
f
。为此,应考虑用户定义的转换序列,其包括标准转换、用户定义转换和另一标准转换(§13.3.3.1.2/1)。用户定义的转换可以通过转换构造函数
B::B(const A&)
或转换函数
A::operator B()
进行

这就是它变得棘手的地方。标准中有一些令人困惑的措辞:

由于隐式转换序列是一个初始化,因此初始化的特殊规则 按用户定义转换为用户定义转换选择最佳用户定义转换时应用 顺序(见13.3.3和13.3.3.1)

(§13.3.3.1.2/2)

长话短说,这意味着在用户定义的转换序列中,从
a
B
的用户定义转换本身要进行重载解析
A::operator B()
胜过
B::B(常数A&)
,因为前者具有较少的cv限定条件(如复制初始化情况),如果我们使用
B::B(A&)
而不是
B::B(常数A&)
,则会导致歧义。请注意,这不会导致重载解析的无限递归,因为不允许将参数转换为用户定义转换的参数类型

返回语句 在

表达式
A()
被隐式转换为类型
B
(§6.6.3/2),因此相同的规则适用于函数参数的隐式转换<将调用code>A::operator B()
,如果使用
B::B(A&)
,则重载将不明确。然而,如果它是

return {A()};
然后,这将是一个副本列表初始化(再次是§6.6.3/2)<代码>B::B(常量A&)
将被调用

注意:处理异常时不尝试用户定义的转换;a
catch(B)
块不会处理a