3 回答
This is a consequence of how overload resolution is defined for the ->
operator. Quoting from C++14 [over.match.oper]/3:
For the operator
,
, the unary operator&
, or the operator->
, the built-in candidates set is empty.
That is, if the left side operand of ->
is of class or enumeration type, then the ->
will never have its built-in meaning; instead, name lookup for operator->
as a member of the left side operand's class must succeed.
If the built-in ->
operator were a candidate, then the compiler could consider implicit conversions that would allow B
to be converted to a type that the built-in ->
could take, but it is not a candidate, so that doesn't happen.
Because C++ will only implicitly convert a class instance when it knows what it should convert to. If you use expressions like b->
, it can't know what pointer type (if any) you would want to convert it to, and will just use the normal operators (which are not defined unless overloaded):
B b;
// calls B::operator-> since that's what you tell it to do
b->i;
// calls B::operator A* since it knows it's implicitly converting to A*
A *a = b;
If you want to use the first expression here, the correct way is to overload operator->
:
class B {
/* ... */
A* operator ->() { return &a; }
}
but I don't understand why implicit conversion doesn't take place.
There's no context for it to take place in. operator->
applies implicitly to pointers, or to class types with that operator defined. But that's it. There's no other sequence through which the compiler will look to find it. In this case, the built-in candidate set for b->
is empty, there is no operator->
, hence compile error.
You just want to add:
A* operator->() { return &a; }