Here is my code example:
class X
{
public:
void f() {}
};
class Y : public X
{
public:
X& operator->() { return *this; }
void f() {}
};
int main()
{
Y t;
t.operator->().f(); // OK
t->f(); // error C2819: type 'X' does not have an overloaded member 'operator ->'
// error C2232: '->Y::f' : left operand has 'class' type, use '.'
}
Why the compiler is trying to "move the responsibility" for operator-> from Y to X? When I implement X::op-> then I cannot return X there - compile error says "infinite recursion" while returning some Z from X::op-> again says that Z doesn't have operator->, thus going higher and higher in hierarchy.
Can anyone explain this interesting behavior? :)
The problem is that operator ->
is supposed to return a pointer, not a reference. The idea is that operator ->
should return a pointer to the real object that should have the pointer applied to it. For example, for a class with an overloaded operator ->
, the code
myClass->myValue;
translates into
(myClass.operator-> ())->myValue;
The problem with your code is that operator ->
returns a reference, so writing
myClass.operator->().f();
is perfectly legal because you're explicitly invoking the operator, but writing
myClass->f();
is illegal, because the compiler is trying to expand it to
myClass.operator->()->f();
and the return type of operator->
isn't a pointer.
To fix this, change your code so that you return a pointer in operator ->
. If you want to overload an operator to return a reference, overload operator *
; pointer dereferences should indeed produce references.
Because that's how overloaded ->
works in C++.
When you use overloaded ->
, expression a->b
is translated into a.operator->()->b
. This means that your overloaded operator ->
must return something that will itself support another application of operator ->
. For this reason a single invocation of overloaded ->
might turn into a long chain of invocations of overloaded ->
s until it eventually reaches an application of built-in ->
, which ends the chain.
In your case you need to return X*
from your overloaded ->
, not X&
.
The syntax is wrong, should be:
T->T2
T2* T::operator ->();
Look at wikipedia's article: Operators in C and C++
If you want to overload, you must use the right syntax for the overloaded operator
You probably want:
class Y : public X
{
public:
X* operator->() { return this; }
void f() {}
};