виртуальный метод ведет себя по-разному с множественным наследованием

почему это работает

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 (предварительный выпуск)

1

Решение

Здесь виртуальность не имеет значения, и тот факт, что 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)

Помните: это чисто неопределенность поиска имени пользователя.

0

Другие решения

Других решений пока нет …