Reputation: 623
In this code, two methods were used to allow conversion of Y object into X object. compiling by g++ always choose constructor. if constructor is private like :
private : Y(const X&){std::cout << "Y constructor...\n" ; }
conversion is prevented either by operator or constructor. if constructor is private and explicit
private : explicit Y(const X&){std::cout << "Y constructor...\n" ; }
compiler use operator instead. Is it the usual way to prevent auto conversion by making conversion constructor private and what is the rule that compiler use to make such kind of conversion.
#include <iostream>
class Y ;
class X {
public:
operator Y()const ;
};
class Y {
public:
Y(){}
private :
explicit Y(const X&){std::cout << "Y constructor...\n" ; }
};
X::operator Y() const { std:: cout << "Operator Y...\n" ;
return Y ();
}
void func(Y Y_object) {}
int main() {
X X_object ;
Y Y_object ;
func(X_object) ;
Y_object = X_object ;
}
Upvotes: 1
Views: 223
Reputation: 96810
Conversion functions and converting-constructors designate conversions from the type for which the conversion function/constructor is made to the type that is taken in the parameter. In other words, you are converting from an X
to a Y
and not the other way around as you said.
When there is a conversion from X
to Y
, the compiler considers the best conversion possible through function overload resolution. Since access control is not considered during overload resolution, it is possible for a private conversion to be chosen over one that is public if the private one is a more viable conversion. There can also be an ambiguity between two conversions if they are both equally viable.
Calling the function func(X_object)
requires an implicit conversion from X
to Y
. Considering both X::operator Y() const
and the converting constructor explicit Y::Y(const X&)
, the conversion operator is chosen because the constructor is marked as explicit
and therefore only can be called through the direct-initialization syntax or an explicit cast.
func(Y(X_object));
func(static_cast<Y>(X_object));
These both call the explicit converting-constructor because the argument type of the constructor and parameter matches exactly.
The same situation occurs when using copy-assignment to implicitly convert an X
to a Y
. The implicit conversion operator is a more viable function than the explicit constructor:
Y_object = X_object; // calls X_object.operator Y()
If direct-initialization syntax or an explicit cast is used, the converting-constructor will be the best viable function.
To prevent an implicit conversion from an X
to a Y
, it is best that you give Y
an explicit constructor rather than an explicit conversion operator. In this case there doesn't seem to be a reason to make the constructor private unless you want to prevent the conversion all together, but if you wanted to do that then simply leave the constructor undeclared.
Upvotes: 2
Reputation: 18556
The most usual way to prevent implicit type conversion is not to declare conversion operator at all and make the constructor explicit
. However, if you want to keep the conversion operator, you can make explicit too using explicit
keyword:
class X {
public:
explicit operator Y() const;
};
Upvotes: 0