It is said that the arrow operator is applied recursively. But when I try to execute the following code, it prints gibberish when it is supposed to print 4.
class dummy
{
public:
int *p;
int operator->()
{
return 4;
}
};
class screen
{
public:
dummy *p;
screen(dummy *pp): p(pp){}
dummy* operator->()
{
return p;
}
};
int main()
{
dummy *d = new dummy;
screen s(d);
cout<<s->p;
delete d;
}
The deal is once
screen::operator->()
returns a pointer (dummy*
) the recursion stops because built-in (default)->
in used on that pointer. If you want recursion you should returndummy
ordummy&
fromscreen::operator->()
What Stanley meant by “recursive” is just that the operator is applied to every returned object until the returned type is a pointer.
Which happens here on the first try:
screen::operator ->
returns a pointer. Thus this is the last call to anoperator ->
that the compiler attempts. It then resolves the right-hand sice of the operator (p
) by looking up a member in the returned pointee type (dummy
) with that name.Essentially, whenever the compiler finds the syntax
aᵢ->b
in code, it essentially applies the following algorithm:aᵢ
of pointer type? If so, resolve memberb
of*aᵢ
and call(*aᵢ).b
.aᵢ::operator ->
aᵢ₊₁ = aᵢ::operator ->()
. Goto 1.I’m hard-pressed to come up with a short, meaningful example where a chain of
operator ->
invocations even makes sense. Probably the only real use is when you write a smart pointer class.However, the following toy example at least compiles and yields a number. But I wouldn’t advise actually writing such code. It breaks encapsulation and makes kittens cry.
C++ Primer (5th edition) formulates it as follows on page 570: