у меня есть программа со следующей структурой наследования
List
/ \
DoublyLinkedList CircularlyLinkedList
\ /
CircularlyDoublyLinkedList
в List
класс (который полностью абстрактный) у меня есть чисто виртуальная функция
int virtual insert(List **head, int position) = 0;
который я переопределил в DoublyLinkedList
а также CircularlyLinkedList
классы.
Для устранения неоднозначности в CircularlyDoublyLinkedList
класс, я явно указываю, какая версия insert()
функция для наследования с использованием оператора разрешения области ::
, например: DoublyLinkedList::insert(..)
Моя проблема в том, что это утверждение
List *cdll_head = new CircularlyDoublyLinkedList();
выдает ошибку
"cannot convert CircularlyDoublyLinkedList* to List*"
когда я изменяю утверждение как
CircularlyDoublyLinkedList *cdll_head = new CircularlyDoublyLinkedList();
Я получаю еще одну ошибку как insert(...)
принимает параметр типа List**
Как мне решить эту проблему без приведения?
При использовании множественного наследования с ромбовидными структурами, вы должны использовать виртуальный наследование.
Я предполагаю, что ваш код выглядит примерно так:
class List {
...
};
class DoublyLinkedList: public List {
...
};
class CircularlyLinkedList: public List {
...
};
class CircularlyDoublyLinkedList: public DoublyLinkedList, public CircularlyLinkedList {
...
};
void doStuff() {
List* aList = new CircularlyDoublyLinkedList();
...
}
которая выдает следующую ошибку:
ambiguous conversion from derived class 'CircularlyDoublyLinkedList' to base class 'List':
class CircularlyDoublyLinkedList -> class DoublyLinkedList -> class List
class CircularlyDoublyLinkedList -> class CircularlyLinkedList -> class List
Если вы измените наследование DoublyLinkedList и CircularlyLinkedList на виртуальную общедоступную версию следующим образом:
class DoublyLinkedList: virtual public List {
...
};
class CircularlyLinkedList: virtual public List {
...
};
class CircularlyDoublyLinkedList: public DoublyLinkedList, public CircularlyLinkedList {
...
};
все должно правильно скомпилироваться. Тем не менее, есть дополнительные эксплуатационные расходы. Я бы предложил использовать полностью абстрактный интерфейс списка, который был бы унаследован всеми вашими классами списка, и композицию, позволяющую повторное использование реализации.
Других решений пока нет …