Неоднозначная база с множественным наследованием - PullRequest
23 голосов
/ 26 августа 2011

Я пытаюсь написать несколько подклассов классов в большой библиотеке. Я получаю ошибку "неоднозначная база" Вот компилируемый пример проблемы:

#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;
}

Ошибка

ошибка: «InteractorStyle» является неоднозначной основой «PointSelector2D».

Что я могу сделать в этом случае?

Ответы [ 4 ]

17 голосов
/ 26 августа 2011

Ваша проблема в том, что стиль Interactor наследуется дважды - один раз PointSelector2D и один раз InteractorStyleCamera. Это означает, что у вас есть 2 версии каждого члена этого класса в вашем классе.

Выезд:

Как можно избежать Алмаза Смерти при использовании множественного наследования?

И попробуйте виртуальное наследование.

5 голосов
/ 26 августа 2011

Вы можете поверхностно «исправить» это с помощью двухступенчатого приведения.Например,

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 голосов
/ 26 августа 2011

Полагаю, вы можете исправить это, используя dynamic_cast вместо static_cast. dynamic_cast может посмотреть на объект во время выполнения, чтобы определить, на какой из двух InteractorStyle базовых классов указывается, и оттуда может настроить указатель вниз до соответствующего типа.

0 голосов
/ 26 августа 2011

Вы можете получить свой код для компиляции (я получил ваш пример по крайней мере для компиляции), добавив InteractorStyle к классам, от которых наследуется PointSelector2D. Является ли это долгосрочным решением, я не знаю.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...