7
votes

I've seen a couple of examples that demonstrate the visitor pattern. In all of them, each derived visited element implements what's usually called the Accept() method.

In a hierarchy of colors, this method might look like:

void Red::accept(Visitor *v)
{
    v->visit(*this);
}

void Blue::accept(Visitor *v)
{
    v->visit(*this);
}

When Visitor, as well as its inheritors, have the methods:

visit(Red red);
visit(Blue blue)

My question is why not implement this in the same way only in the base class (in this example: Color) and polymorphism will do the job, namely, the correct visit will be called since when the object is a Red the this's dynamic type is a Red so dereferencing it will yield a Red which in turn will cause the visit(red) to be called?

What am I missing?

3
if you want it in a base class then you have to use the Curiously recurring template pattern the get the right this. - user1810087
In a more dynamic language you might have to name the functions visitBlue, and visitRed instead. You could do that here as well. Does that help it make sense? - Peter Wood
The answer has already been provided, but you can find more information searching the web for "double dispatch" (I assume that you have already searched "visitor pattern" and it did not help you), which is the name of the technique used here. - David Rodríguez - dribeas
@DavidRodríguez-dribeas, thanks! - Subway

3 Answers

8
votes

Inheritance polymorphism (dynamic dispatch) does not apply to function arguments. In other words, overloaded function are selected on the static type of the arguments being passed. If implemented in the base class Color, the v->visit(*this) would always call visit(Color c).

1
votes

If the only accept you had was...

void Color::accept(Visitor* v)
{
    v->visit(*this);
}

visit would just get called with a base class. In order to call visit with the correct derived class you need each Color to implement it so they can pass a correctly typed this, so the correct visit overload is called.

1
votes

My understanding is that in base class methods the this pointer is of type base, not of any derived classes, hence it can only access base class methods, and is passed as type Color* this. When passed to the visit method it would try and run visit(Color* color), as polymorphic behavior only applies to methods of the class itself (not other classes).