C++ - 为什么这种菱形继承结构不会引起歧义?

C++ - Why isn't this structure of diamond inheritance cause an ambiguity?

我浏览了数十个多重继承问题,但未能找到该问题的答案。

我明白为什么这不会编译:

struct B{
    virtual void f(){
        printf("B");
    }
};

struct C1 : virtual B{
   void f() override{
        printf("C1");
    }
};

struct C2: virtual B{
    void f() override{
        printf("C2")
    }
};

struct D: C1,C2{
    
};

因为无法确定 f 应该在 B 的 vtable 中。

但是,我很惊讶地看到这段代码可以编译:

struct B{
    virtual void f(){
        printf("B");
    }
};

struct C1 : virtual B{
   void f() override{
        printf("C1");
    }
};

struct C2: virtual B{

};

struct D: C1,C2{
    
};

我的(错误的)直觉是我们仍然有从 DB 的两条路径,并且在每条路径中最后一个 f 被覆盖的地方是不同的 - 在一条路径中它是在 C1 中,在一个路径中它在 B 中,但这确实可以编译。

为什么这不会引起歧义?

因为 C1::f1 覆盖 B::f1,它将优先用于具有动态类型 C1 或任何子类的任何对象。

在模棱两可的情况下,虽然 C1::f1 和 C2::f1 都会覆盖 B::f1,但它们不会相互覆盖,所以歧义存在于它们之间——事实上它们都是重写一个公共基础函数是无关紧要的。