Неоднозначная база с множественным наследованием
Я пытаюсь написать некоторые подклассы классов в большой библиотеке. Я получаю ошибку "неоднозначной базы". Вот компилируемый пример проблемы:
#include <iostream>
// I can't change these because they are in the library:
class InteractorStyle {};
class InteractorStyleCamera : public InteractorStyle {};
class InteractorStyleImage : public InteractorStyle {};
// These are my subclasses (so I can change them):
class PointSelector : public InteractorStyle {};
class PointSelector2D : public InteractorStyleCamera, public PointSelector
{
// This function has to exist exactly like this (a requirement of the library):
static PointSelector2D* SafeDownCast(InteractorStyle *o)
{
return static_cast<PointSelector2D *>(o);
}
};
int main()
{
return 0;
}
Ошибка
error: "InteractorStyle - это двусмысленная база" PointSelector2D ".
Есть ли что-нибудь, что я могу сделать в этом случае?
Ответы
Ответ 1
Ваша проблема в том, что стиль Interactor наследуется дважды - один раз PointSelector2D и один раз InteractorStyleCamera. Это означает, что у вас есть 2 версии каждого члена, содержащиеся в вашем классе.
Отъезд:
Как я могу избежать Diamond of Death при использовании множественного наследования?
И попробуйте виртуальное наследование.
Ответ 2
Вы можете поверхностно "исправить" его, используя двухэтапный отбор. Например
static_cast<PointSelector2D *>(static_cast<InteractorStyleCamera *>(o));
Конечно, вы должны иметь в виду, что это "исправляет" синтаксис, но не устраняет основную структурную проблему. Ваш PointSelector2D
имеет два субъекта базы данных InteractorStyle
. В зависимости от того, с каких начальных подобъектов InteractorStyle
вы запускаете, путь повышения скорости отличается. И очень важно принять правильный путь. То, что я написал выше, для InteractorStyle
внутри InteractorStyleCamera
. Для другой базы правильный upcast будет
static_cast<PointSelector2D *>(static_cast<PointSelector *>(o));
Если вам задан указатель InteractorStyle *
без дополнительной информации о том, к какой базе он указывает, то вы не можете решить свою проблему с помощью static_cast
. Там нет способа узнать, какой путь upcast принять. Взятие неправильного приведет к совершенно бессмысленному результату.
Как уже отмечалось, dynamic_cast
может помочь в этой ситуации, но имеет дополнительные требования (полиморфный стартовый тип). Ваши типы не являются полиморфными (по крайней мере, в приведенном ниже примере), поэтому dynamic_cast
не будет принимать их для повышения.
Ответ 3
Я считаю, что вы можете исправить это, используя dynamic_cast
вместо static_cast
. dynamic_cast
может посмотреть объект во время выполнения, чтобы определить, какой из двух базовых классов InteractorStyle
указывается, и оттуда можно настроить указатель до соответствующего типа.
Ответ 4
Вы можете получить свой код для компиляции (я получил ваш пример для компиляции, по крайней мере), добавив InteractorStyle
к классам, которые наследует PointSelector2D
. Является ли это долгосрочным решением, я не знаю.