因为在C++;当存在两种相同转换的可能性时,它们如何相互作用? 我只是想澄清C++是如何工作的,这不是真正的解决我的代码中的一个特殊问题。 在C++中,你可以说类型A应该用两种不同的方式隐式转换为B。
如果您是A的作者,您可以在A中添加以下内容:因为在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
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
(C++11标准,§5.4/4)static\u cast(a)
- 您使用静态转换,在本例中,它将创建一个临时转换,该转换以与声明
bt(a)相同的方式初始化代码>初始化
;(§5.2.9/4)t
- 您使用的语法是
,它相当于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&)将被调用
注意:处理异常时不尝试用户定义的转换;acatch(B)
块不会处理a