Предупреждение: прямой базовый класс недоступен в производной из-за неоднозначности; это серьезно?

Я не понимаю, в чем здесь двусмысленность. Я определил линию, которая вызывает неоднозначность, и отметил ее.

#include <string>
#include <unordered_map>

class Spell {
protected:
struct Exemplar {};
Spell() = default;
Spell (Exemplar, const std::string&);
};

class SpellFromScroll : virtual public Spell {
private:
static std::unordered_map<std::string, SpellFromScroll*> prototypesMap;
public:
static void insertInPrototypesMap (const std::string& tag, SpellFromScroll* spell) {
prototypesMap.emplace (tag, spell);
}
template <typename T> static SpellFromScroll* createFromSpell (T*);
};
std::unordered_map<std::string, SpellFromScroll*> SpellFromScroll::prototypesMap;

class SpellWithTargets : virtual public Spell {};  // *** Note: virtual

class Sleep : public SpellWithTargets {
private:
static const Sleep prototype;
public:
static std::string spellName() {return "Sleep";}
private:
Sleep (Exemplar e) : Spell (e, spellName()) {}
};
const Sleep Sleep::prototype (Exemplar{});

template <typename T>
class ScrollSpell : /*virtual*/ public T, public SpellFromScroll {};

Spell::Spell (Exemplar, const std::string& spellName) {
// Ambiguity warning!
SpellFromScroll::insertInPrototypesMap (spellName, SpellFromScroll::createFromSpell(this));
}

template <typename T>
SpellFromScroll* SpellFromScroll::createFromSpell (T*) {
return new ScrollSpell<T>;
}

int main() {}

/*
c:\ADandD>g++ -std=c++14 Ambiguity.cpp -o a.exe -Wall -Wextra -pedantic-errors
Ambiguity.cpp: In instantiation of 'class ScrollSpell<Spell>':
Ambiguity.cpp:32:13:   required from 'static SpellFromScroll* SpellFromScroll::createFromSpell(T*) [with T = Spell]'
Ambiguity.cpp:27:90:   required from here
Ambiguity.cpp:23:7: warning: direct base 'Spell' inaccessible in 'ScrollSpell<Spell>' due to ambiguity
class ScrollSpell : public T, public SpellFromScroll {};
^
Ambiguity.cpp:23:7: warning: virtual base 'Spell' inaccessible in 'ScrollSpell<Spell>' due to ambiguity [-Wextra]

c:\ADandD>
*/

Насколько это серьезно и что может пойти не так в дальнейшем по мере развития программы?

Обновить: Решение найдено, позволяя T быть виртуальной базой ScrollSpell<T>,
Но в моей программе T всегда является производным классом Spell, а Spell всегда является виртуальной базой T. См. Диаграмму ниже.

                  Spell
/   \
v  /     \ v
/       \
/         \
SpellFromScroll      SpellWithTargets
\                \
\                \
\               Sleep
\               /
\             / v
\           /
ScrollSpell<Sleep>

На рисунке выше, почему Sleep быть виртуальной базой ScrollSpell<Sleep> решать проблему?

1

Решение

template <typename T>
class ScrollSpell : public T, public SpellFromScroll {};

Вот, T = Spell, Итак ScrollSpell класс имеет Spell класс как прямой, не виртуальный базовый класс, а также как виртуальный базовый класс через SpellFromScroll, Это двусмысленность. Объявление базового класса T как виртуальный может решить проблему.

Кроме того, я не совсем понимаю смысл дизайна, что может привести к совершенно новым проблемам.

4

Другие решения

Чтобы уточнить ответ Питера Б., я нарисовал диаграмму классов, которая получается, когда Т = Заклинание. Компилятор не знает, какой путь выбрать для Scroll при создании экземпляра ScrollSpell. Но это также показывает, что использование виртуального наследования не решает двусмысленность. Результатом обоих методов является два пути к Spell что неоднозначно.

            ╔══════╗
║Spell ║
╚══════╝
/      \
╔═══════════════╗   \
║SpellFromScroll║    \
╚═══════════════╝    /
\      /
╔═══════════╗  T=Spell
║ScrollSpell║
╚═══════════╝
2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector