Reputation: 32635
Why is the Child class's converter constructor called in the code below?
I mean, it automatically converts Base to Child via the Child converter constructor. The code below compiles, but shouldn't it not compile since I haven't provided bool Child::operator!=(Base const&)
?
class Base
{
};
class Child : public Base
{
public:
Child() {}
Child(Base const& base_) :
Base(base_)
{
std::cout <<"should never called!";
}
bool operator!=(Child const&)
{
return true;
}
};
void main()
{
Base base;
Child child;
if(child != base)
std::cout << "not equal";
else
std::cout << "equal";
}
Upvotes: 3
Views: 325
Reputation: 35925
The function with the signature Child(Base const& base_)
is not a copy constructor (the right hand side type is not the same as the left's). That constructor can be used implicitly by the compiler to coerce one type into another for the purpose of the comparison you are making in main
. To prevent this mark the constructor explicit
.
Upvotes: 6
Reputation: 8072
Because Child cannot be compared to Base - it can only be compared to another Child. Thus, your compiler creates an implicit copy of Base to Child in order to cause the conversion. If you change your code to:
class Child : public Base
{
public:
Child() {}
explicit Child(Base const& base_) :
Base(base_)
{
std::cout <<"should never called!";
}
bool operator!=(Child const&)
{
return true;
}
};
You'll find that it no longer compiles.
Upvotes: 1
Reputation: 69672
Because you don't provide any operator!=() that take Base as argument : the compiler will try "what he can" and see that there is a conversion constructor to the argument type (Child) that can be called. So it use it to make the != work.
Upvotes: 0
Reputation: 47762
Because you provided a conversion constructor. If you don't want the compiler to automatically convert Base
objects to Child
using the
Child(Base const& base_)
constructor, make it explicit:
explicit Child(Base const& base_)
This way, the constructor will only be called when you explicitly specify it, in contexts like:
Child ch(base);
foo(Child(base));
new Child(base);
Upvotes: 3