隐式转换 C++

Implicit casting C++

考虑这个案例:

ClassA obA;
ClassB obB;

obA = obB;

如果ClassA有一个参数类型为ClassB的构造函数,在这种情况下会被调用吗?

如果 ClassB 中有一个重载的转换运算符 - 将 ClassB 对象转换为 ClassA 对象,将调用运算符方法。如果有相应的构造函数和重载的转换运算符,将调用哪一个?我在哪里可以阅读它?

此代码:

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
    }
};

If there is an overloaded casting operator in ClassA which has a parameter of type ClassB [...].

你的意思是 constructor,而不是 casting operator,对吧?您尝试将 ClassA 转换为 ClassB,因此来自 ClassA 的转换运算符在这种情况下无关紧要。


(*) 您在 obA 构造之后将 obB 分配给 obA,因此在您的情况下只有第二点适用.您还可以通过添加赋值运算符使其工作:

3.

class ClassA
{
public:
    ClassA& operator=(const ClassB& b)
    {
        //assign b to *this
    }
};

在你的情况下会被调用。

Is it right, that if ClassA has a constructor which has a parameter of type ClassB, it will be called in this case?

是的,构造函数被考虑用于隐式类型转换:

Type conversions of class objects can be specified by constructors and by conversion functions. These conversions are called user-defined conversions and are used for implicit type conversions (Clause 4), for initialization (8.5), and for explicit type conversions (5.4, 5.2.9).

具有签名 ClassA::ClassA(ClassB) 的构造函数称为 converting-constructor。在赋值等函数调用期间,构造函数和用户定义的转换运算符被编译成重载集,并选择最佳的进行转换。

如果选择构造函数:如果源类型是按值类型,它将创建源类型 (ClassA) 类型的纯右值,并使用目标类型 (ClassB), 用于初始化参数。如果源类型是引用,则使用 reference-initialization rules


赋值运算符在 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() 都是用于转换的可行转换函数。因此,转换是不明确的,我们会得到一个编译错误。

User-defined conversions are applied only where they are unambiguous (10.2, 12.3.2).

如果我们将 class A 中的转换构造函数的签名更改为 A::A(B const&),那么将使用 B 中的转换运算符,因为 A的构造函数需要限定转换(添加const)。

cppreference 上有一个主题,您可以在其中了解更多信息。