почему это работает
struct Base {
virtual void visit(const A &) { };
virtual void visit(const B &) { };
}
и это жалуется на неоднозначность при вызове метода посещения
template< typename T >
struct X {
virtual void visit(const T &) { };
};
struct Base: X< A >, X< B > { };
это также показывает ту же проблему:
struct Y {
virtual void visit(const A &) { };
};
struct Z {
virtual void visit(const B &) { };
};
struct Base: Z, Y { };
каким-то образом это выглядит как множественное наследование мешает с сигнатурами виртуальной функции …
с версией gcc 4.8.0 20130411 (предварительный выпуск)
Здесь виртуальность не имеет значения, и тот факт, что 2 базовых класса являются шаблонными классами, не имеет значения. Более простой код с той же проблемой:
struct A {
void f(const A &) { }
};
struct B {
void f(const B &) { }
};
struct Der: A,B { };
Вот Der
имеет два унаследованных члена: A::f(const A &)
а также B::f(const B &)
; они могут быть вызваны следующим образом:
Der d;
d.A::f(d);
d.B::f(d);
но не сюда:
d.f((A&)d); // error: ambiguous name lookup
d.f((B&)d); // error: ambiguous name lookup
Разрешение перегрузки функции-члена не работать так, как вы думаете (найти оба f
затем оставьте тот, у которого есть список совместимых аргументов).
В C ++ член поиск по имени находит все не скрытые объявления членов с заданным именем, поэтому здесь он находит A::f(const A &)
а также B::f(const B &)
, тогда это немедленно терпит неудачу, если эти члены не объявлены в том же классе.
Вы можете решить эту проблему, добавив 2 объявления в одном классе:
struct Der: A,B {
using A::f; // imports A::f(const A &)
using B::f; // imports B::f(const B &)
};
Тогда вы можете сделать:
Der d;
d.f((A&)d); // OK: Der::f(&A)
Помните: это чисто неопределенность поиска имени пользователя.
Других решений пока нет …