Reputation: 189
Consider this case:
ClassA obA;
ClassB obB;
obA = obB;
Is it right, that if ClassA
has a constructor which has a parameter of type ClassB
, it will be called in this case?
If there is an overloaded casting operator in ClassB
- which converts ClassB
object to ClassA
object, the operator method will be called. If there is corresponding constructor and overloaded casting operator which one will be called? Where can I read about it?
Upvotes: 3
Views: 2223
Reputation: 96875
Is it right, that if
ClassA
has a constructor which has a parameter of typeClassB
, it will be called in this case?
Yes, constructors are considered for implicit type conversions:
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).
A constructor with the signature ClassA::ClassA(ClassB)
is called a converting-constructor. During a function call such as the assignment, constructors and user-defined conversion operators are compiled into an overload set and the best one is chosen for the conversion.
If a constructor is chosen: If the source type is a by-value type, it creates a prvalue of the type of the source type (ClassA
) initialized with the type of the destination type (ClassB
), and that is used to initialize the parameter. If the source type is a reference, reference-initialization rules are used.
The assignment operators are implicitly-generated in ClassA
(assuming they haven't been overriden). They are:
ClassA& operator=(ClassA const&);
ClassA& operator=(ClassA &&);
An implicit-conversion sequence can choose either a constructor or conversion function to convert from ClassB -> ClassA const&
or ClassB -> ClassA&&
.
However, in this case, going by your scenario, the conversion would not be able to succeed as it would be ambiguous. Consider:
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
}
Both A::A(B)
and B::operator A()
are both viable conversion functions to use for the conversion. As such, the conversion is ambiguous and we are given a compile error.
User-defined conversions are applied only where they are unambiguous (10.2, 12.3.2).
If we change the signature of the converting-constructor in class A
to A::A(B const&)
, then the conversion operator in B
will be used because the A
's constructor requires a qualification-conversion (addition of const
).
There is a thread on cppreference where you can learn more.
Upvotes: 4
Reputation: 12118
This code:
ClassA obA;
ClassB obB;
obA = obB;
is not what you think it is (*). This code:
ClassB obB;
ClassA obA = obB;
will work (as provided) if:
1. ClassA
has constructor, that accepts ClassB
as parameter:
class ClassA
{
public:
ClassA(const ClassB& b)
{
//construct *this from b
}
};
2. ClassB
has defined conversion-to-type operator:
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 [...].
You meant constructor, not casting operator, right? You try to convert ClassA
to ClassB
, so conversion operators from ClassA
are irrelevant in this case.
(*) You assign obB
to obA
after obA
's construction, so in your case only second point is applicable. You can also make it work by adding assignment operator:
3.
class ClassA
{
public:
ClassA& operator=(const ClassB& b)
{
//assign b to *this
}
};
which would be called in your case.
Upvotes: 3