Я видел пару примеров, которые демонстрируют шаблон посетителей.
Во всех них каждый производный посещенный элемент реализует то, что обычно называется методом Accept ().
В иерархии цветов этот метод может выглядеть следующим образом:
void Red::accept(Visitor *v)
{
v->visit(*this);
}
void Blue::accept(Visitor *v)
{
v->visit(*this);
}
Когда Visitor, как и его наследники, имеют методы:
visit(Red red);
visit(Blue blue)
Мой вопрос: почему бы не реализовать это таким же образом только в базовом классе (в этом примере: Color
) и полиморфизм сделает эту работу, а именно, правильное посещение будет вызвано, так как, когда объект является Red
динамический тип этого является Red
так разыменование это приведет к Red
что в свою очередь вызовет визит (красный)?
Что мне не хватает?
Полиморфизм наследования (динамическая диспетчеризация) не применяется к аргументам функции. Другими словами, перегруженные функции выбираются по статическому типу передаваемых аргументов. Если реализовано в базовом классе Color
, v->visit(*this)
всегда будет звонить visit(Color c)
,
Если только accept
ты был …
void Color::accept(Visitor* v)
{
v->visit(*this);
}
visit
просто вызвали бы с базовым классом. Для того, чтобы позвонить visit
с правильным производным классом вам нужен каждый Color
реализовать его, чтобы они могли передать правильно набранный this
так правильный visit
перегрузка называется.
Насколько я понимаю, в методах базового класса this
Указатель относится к типу base, а не к каким-либо производным классам, поэтому он может обращаться только к методам базового класса и передается как тип Color* this
, При переходе к методу посещения он будет пытаться запустить visit(Color* color)
, поскольку полиморфное поведение применимо только к методам самого класса (но не к другим классам).