考虑这个情况:
ClassA obA;
ClassB obB;
obA = obB;
如果ClassA
有一个参数类型为ClassB
的构造函数,那么在这种情况下它会被调用吗?
如果ClassB
中有一个重载的转换运算符 - 将ClassB
对象转换为ClassA
对象,则将调用运算符方法。如果存在相应的构造函数和重载的转换运算符,哪一个会被调用?我在哪里可以阅读相关信息?
考虑这个情况:
ClassA obA;
ClassB obB;
obA = obB;
如果ClassA
有一个参数类型为ClassB
的构造函数,那么在这种情况下它会被调用吗?
如果ClassB
中有一个重载的转换运算符 - 将ClassB
对象转换为ClassA
对象,则将调用运算符方法。如果存在相应的构造函数和重载的转换运算符,哪一个会被调用?我在哪里可以阅读相关信息?
ClassA
有一个以ClassB
为参数的构造函数,那么在这种情况下它是否会被调用?ClassA::ClassA(ClassB)
的构造函数称为转换构造函数。在函数调用(例如赋值)期间,构造函数和用户定义的转换运算符被编译成重载集,并选择最佳构造函数进行转换。ClassA
)的类型的prvalue,该类型已使用目标类型(ClassB
)初始化,并用于初始化参数。如果源类型是引用,则使用引用初始化规则。
ClassA
中被隐式生成(假设它们没有被覆盖)。它们是:ClassA& operator=(ClassA const&);
ClassA& operator=(ClassA &&);
ClassB -> ClassA const&
或 ClassB -> ClassA&&
。但是,在这种情况下,根据您的方案,转换将无法成功,因为它将是模棱两可的。请考虑:struct B { operator struct A(); };
struct A {
A() = default;
A(B) {}
};
B::operator A() { return A(); }
int main()
{
A a; B b;
a = b; // Error! Ambiguous conversion
}
A::A(B)
和B::operator A()
都可以用于转换,因此转换是不明确的,编译时会出错。
如果我们将类只有在没有歧义的情况下才应用用户定义的转换(参见10.2、12.3.2)。
A
中的转换构造函数的签名更改为A::A(B const&)
,则将使用B
中的转换运算符,因为A
的构造函数需要一个限定词转换(添加const
)。ClassA obA;
ClassB obB;
obA = obB;
这不是你想象中的那样(*)。这段代码:
ClassB obB;
ClassA obA = obB;
如果满足以下条件,代码将正常工作:
1. ClassA
有一个接受ClassB
为参数的构造函数:
class ClassA
{
public:
ClassA(const ClassB& b)
{
//construct *this from b
}
};
2. ClassB
定义了类型转换运算符:
class ClassB
{
public:
operator ClassA() const
{
//construct ClassA from *this
}
};
ClassA
转换为ClassB
,因此在此情况下来自ClassA
的转换运算符是不相关的。
(*) 在obA
构造之后将obB
分配给obA
,因此对于您的情况,只适用第二个点。您还可以通过添加赋值运算符使其工作:
3.
class ClassA
{
public:
ClassA& operator=(const ClassB& b)
{
//assign b to *this
}
};