У меня есть программа со следующей структурой наследования
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 {
...
};
все должно компилироваться должным образом. Однако есть дополнительная стоимость исполнения. Я бы предложил использовать полностью абстрактный интерфейс списка, который будет унаследован всеми вашими классами списков и состав, чтобы повторное использование реализации.