Следующий код представляет собой упрощенную версию VisitorPattern, которую я реализовал в своем проекте.C++ Visitor Pattern and Polymorphism
#include <iostream>
class AVisitor {
public:
virtual void visit(class A *) = 0;
};
class ExtendedVisitor : public AVisitor {
public:
virtual void visit(class B *) = 0;
};
class A {
public:
virtual void accept(AVisitor *visitor) {
std::cout << "Call accept of A" << std::endl;
visitor->visit(this);
}
};
class B : public A {
public:
void accept(AVisitor *visitor) override {
std::cout << "Call accept of B" << std::endl;
B *just_this = this;
visitor->visit(just_this); //why this calls to visit(A*)
visitor->visit((B*) just_this); //useless casting
}
};
class ActualVisitor : public ExtendedVisitor {
public:
void visit(A *x) override {
std::cout << "Call visit on A*" << std::endl;
}
void visit(B *x) override {
std::cout << "Never called" << std::endl;
}
};
int main() {
ActualVisitor visitor;
A *a = new B();
a->accept(&visitor);
}
Я не понимаю, почему метод принимает класса B вызывает к посетителю (A *) метод вместо посетителей (B *). Основные функции принты
Call accept of B
Call visit on A*
Call visit on A*
Вместо этого следующий код ведет себя, как я ожидал:
#include <iostream>
class AVisitor {
public:
virtual void visit(class A *) = 0;
virtual void visit(class B *) = 0;
};
class A {
public:
virtual void accept(AVisitor *visitor) {
std::cout << "Call accept of A" << std::endl;
visitor->visit(this);
}
};
class B : public A {
public:
void accept(AVisitor *visitor) override {
std::cout << "Call accept of B" << std::endl;
B *just_this = this;
visitor->visit(just_this); //now it works
visitor->visit((B*) just_this);
}
};
class ActualVisitor : public AVisitor {
public:
void visit(A *x) override {
std::cout << "Call visit on A*" << std::endl;
}
void visit(B *x) override {
std::cout << "Call visit on B*" << std::endl;
}
};
int main() {
ActualVisitor visitor;
A *a = new B();
a->accept(&visitor);
}
прямо сейчас печатает:
Call accept of B
Call visit on B*
Call visit on B*
Проблема тогда, кажется, удел AVisitor класс. Интересно, почему это происходит и что такое правильный способ разработки VisitorPattern с «специализированными» посетителями (здесь ExtendedVisitor можно также посетить объект B)
Класс ActualVisitor переопределяет оба метода посещения (A *) и посещения (B *), поэтому, поскольку подпись accept принимается (AVisitor * visitor), полиморфизмом, я ожидаю, что вызов посетителя-> посетит (B *), выбрать правильный метод. Что мне не хватает? –
Ваш код не относится к интерфейсу 'ActualVisitor', а относится к интерфейсу' AVisitor'. * Перегруженная * виртуальная функция в 'ActualVisitor' * не * переопределяет метод в' AVisitor'. –
Вижу, вы правы. Тогда, если ActualVisitor не переопределяет посетителя (B *), это означает, что у меня есть не абстрактный класс, который не реализует все чистые виртуальные функции (здесь вы можете посетить (A *) и посетить (B *))? или посещение (A *) - это реализация как посещения (A *), так и посещения (B *) чистых виртуальных функций? –