警告:由于歧义而导致的直接基类无法访问;这是严重的

Warning: direct base class inaccessible in derived due to ambiguity; is this serious?

本文关键字:基类 访问 警告 于歧义 歧义      更新时间:2023-10-16

我不明白这里的歧义是什么。我确实确定了引起歧义并标记的线。

#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始终是派生类别的类别,咒语始终是T的虚拟基础。请参见下面的图。

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

在上图中,为什么SleepScrollSpell<Sleep>的虚拟基础解决问题?

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

在这里,T = Spell,因此ScrollSpell类将Spell类是直接的非虚拟基类,也是通过SpellFromScroll的虚拟基类。那就是歧义。将基类T声明为虚拟可能解决问题。

我也不太了解设计背后的观点,因此可能会引入一些全新的问题。

要详细说明彼得·B的答案,我绘制了当t = spell时产生的类图。编译器不知道在实例化卷轴时要滚动的路径。但是,这也表明,使用虚拟继承并不能解决歧义。两种方法结果都是Spell的两条路径,这是模棱两可的。

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