为什么这个交叉广播的工作方式不同?

Joh*_*cid 6 c++ gcc clang

我发现以下简化示例在 GCC 和 Clang 中的工作方式有所不同:

#include <iostream>

class Body
{
public:
    virtual ~Body()
    {
        std::cout << "Body::~Body()" << std::endl;
    }
};

class HydrophobicObject : public virtual Body
{
};

class ControlledObject : public virtual Body
{
};

class CrawlingObject : public virtual ControlledObject
{
};

class OwnerProtection
{
public:
    void f()
    {
        std::cout << "OwnerProtection::f" << std::endl;
    }
};

class Caterpillar : public CrawlingObject, public OwnerProtection, HydrophobicObject
{
};

int main(int argc, char *argv[])
{
    Caterpillar caterpillar;
    Body& body = caterpillar;
    auto p = dynamic_cast<OwnerProtection&>(body);
    p.f();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果我用 Clang 编译并运行它,则不会发生 bad_cast 异常。如果我用 GCC 编译并运行它,我会得到 bad_cast。但如果我在 HydrophobicObject 之前添加“public”,那么它也适用于 GCC。

为什么“public”对于 GCC 很重要,哪个编译器在这里是正确的?

更新:我使用 macOS Clang:

$ clang -v
Apple clang version 15.0.0 (clang-1500.0.40.1)
Target: x86_64-apple-darwin22.6.0
Thread model: posix
Run Code Online (Sandbox Code Playgroud)