Я читал разные вопросы по этой теме, но не смог найти тот, который бы вполне отвечал тому, что я ищу. Вот образец кода, который у меня есть:
class Base {
public:
virtual void foo(int) const {...}
}
template <class T>
class TmplClass : public Base {
public:
virtual void foo(int i) const { foo(T(i)); }
virtual void foo(T& param) const {
printf("Template::Foo\n");
bar(param);
}
virtual void bar(T&) const {
printf("Template::Bar\n");
}
}
class Derived : public TmplClass<SomeConcreteType> {
public:
void bar(SomeConcreteType&) {
printf("Derived::Bar\n");
}
}
int main() {
Derived d;
Base* b = &d;
b->foo(1);
}
По исполнению я получаю:
Template::Foo
Template::Bar
Почему не работает диспетчеризация вызова на панель? Если я перегружаю foo в Derived, то он вызывает производную версию foo, почему он не может выполнить динамическую диспетчеризацию для bar?
Поскольку я работаю в существующем коде, я бы предпочел не изменять базовую структуру классов здесь. Я надеюсь найти способ заставить звонок работать или понять, почему это не так. Я пробовал много разных вещей, основываясь на прочтении других вопросов здесь, но все безрезультатно.
Оказывается, это не было проблемой шаблона. Проблема с кодом состоит в том, что метод Derived :: bar не помечен как const, где-как метод TmplClass :: bar помечен как const. Таким образом, целью было предоставить перегрузку, но на самом деле Derived :: bar — это совершенно другой метод с другой сигнатурой, поэтому он давал непредвиденное поведение. Как только const удален из TmplClass :: bar или добавлен в Derived :: bar, сигнатуры совпадают и ожидаемый результат получен:
Template::Foo
Derived::Bar
Других решений пока нет …