У меня есть абстрактный базовый класс, который действует как интерфейс.
У меня есть два "набора" производных классов, которые реализуют половину абстрактного класса. (один "набор" определяет абстрактные виртуальные методы, связанные с инициализацией, другой "набор" определяет те, которые связаны с фактической "работой".)
Затем я получил производные классы, которые используют множественное наследование для создания полностью определенных классов (и ничего не добавляет).
Итак: (плохой псевдокод)
class AbsBase {
virtual void init() = 0;
virtual void work() = 0;
}
class AbsInit : public AbsBase {
void init() { do_this(); }
// work() still abs
}
class AbsWork : public AbsBase {
void work() { do_this(); }
// init() still abs
}
class NotAbsTotal : public AbsInit, public AbsWork {
// Nothing, both should be defined
}
Прежде всего, могу ли я это сделать? Могу ли я наследовать от двух классов, которые оба получены из одной базы? (Надеюсь, что так).
Вот "настоящая проблема", хотя (я немного соврал, чтобы упростить пример).
То, что я действительно сделал и сделал, добавляет методы абстрактного доступа к базовому классу:
class AbsBase {
public:
void init() { init_impl(); }
void work() { work_impl(); }
private:
virtual void init_impl() = 0;
virtual void work_impl() = 0;
}
Потому что общая идиома состоит в том, чтобы сделать все виртуальные методы частными.
К сожалению, теперь оба AbsInit и AbsWork наследуют эти методы, и поэтому NotAbsTotal наследует "два из каждого" (я понимаю, что я могу разбить то, что действительно происходит во время компиляции).
В любом случае g++ жалуется, что: "запрос для члена init() неоднозначен" при попытке использовать класс.
Я предполагаю, что если бы я использовал свой класс AbsBase как чистый интерфейс, этого можно было бы избежать (предполагая, что верхний пример действителен).
Итак: - У меня с моей реализацией? - Является ли это ограничением идиомы для создания виртуальных методов? - Как мне реорганизовать мой код, чтобы делать то, что я хочу? (Предоставьте один общий интерфейс, но дайте возможность поменять местами реализации для "наборов" функций-членов)
Edit:
Кажется, я не первый: http://en.wikipedia.org/wiki/Diamond_problem
Кажется, что Virtual Inheritance является решением. Раньше я слышал о виртуальном наследовании, но я не обворачивал его. Я по-прежнему открыт для предложений.