当类的多重继承本身在其层次结构中具有菱形继承时,函数的继承不明确

Zer*_*ero 5 c++ inheritance multiple-inheritance virtual-inheritance msvc12

文字描述下面的代码):我有一个提供类集合的库。对于每组类,我们有两个具体类型,( ClassA_Partial, ClassA), ( ClassB_Partial, ClassB) 等。其中每一个都分别实现 ( Interface_Partial, Interface) 。此外,Interface is a Interface_Partial和each Class? is a Class?_Partial - 创建一个菱形继承模式,其中顶部被虚拟继承。

为什么Interface_Partial函数在继承ClassAand时会产生二义性ClassB

struct Interface_Partial
{ 
    virtual ~Interface_Partial(); 
    virtual void f() = 0;
};

struct Interface
    :
    virtual Interface_Partial
{
    virtual void g() = 0;
};


struct ClassA_Partial : public virtual Interface_Partial
{
    void f() {};
};


struct ClassA : public Interface, public virtual ClassA_Partial
{
    void g() {};
};

struct ClassB_Partial : public virtual Interface_Partial
{
    void f() {};
};


struct ClassB : public Interface, public virtual ClassB_Partial
{
    void g() {};
};

struct MyClass : public ClassA, public ClassB
{ }; // error C2250: MyClass : ambiguous inheritance of 'void Interface_Partial::f(void)'
Run Code Online (Sandbox Code Playgroud)

当我们多次继承一个公共接口时,为什么我们不能像通常那样消除歧义呢?例如

struct ClassX : public Interface_Partial { void f() {} };
struct ClassY : public Interface_Partial { void f() {} };
class Another : public ClassX, public ClassY
{};

void func()
{
    // This is ok
    Another a;
    a.ClassX::f();   

    // Why would this not work?
    // unambiguously refers to the one and only f() function 
    // inherited via  ClassA
    MyClass b;
    b.ClassA::f();   
}
Run Code Online (Sandbox Code Playgroud)

Lub*_*nov 5

由于虚拟继承,基类Interface_Partial只有一个vtable——一旦使用虚拟继承,“虚拟性”就会感染所有级别的所有派生类

继承是不明确的,因为MyClass有两个不同版本的 f() 可用 - 一种来自ClassA,一种来自ClassB。由于 的虚拟继承Interface_Partial,您有两个处于同一级别的派生类实现,并且尝试重写相同的虚拟函数。声明虚拟基类使所有派生类共享该虚拟基类,包括其 vtable。共享虚函数表被更新以包含应调用的虚函数的指针。但由于有两个同样“好”的选项可供选择,因此无法选择其中一个。

在您给出的另一个示例中,是和Interface_Partial的非虚拟基类,因此每个类都重写完全不同的虚拟函数。这对于编译器来说是明确的,尽管当您调用它们时,您必须指定要调用哪个特定的。 ClassXClassYf()

f()您可以通过提供in 的实现来解决此问题MyClass

  • @Zero,由于虚拟继承,基类“Interface_Partial”只有一个虚函数表 - 一旦使用虚拟继承,“虚拟性”就会感染所有级别的所有派生类。 (2认同)