You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GCC与Clang动态_cast行为差异解析:继承权限的影响

GCC与Clang对C++虚继承和dynamic_cast的行为差异分析

示例代码

#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;
}

问题现象

  • 使用Apple clang 15.0.0编译运行时,程序正常输出OwnerProtection::f,不会抛出bad_cast异常;
  • 使用GCC编译运行时,会触发bad_cast异常;
  • 若给Caterpillar继承HydrophobicObject时添加public关键字(即class Caterpillar : public CrawlingObject, public OwnerProtection, public HydrophobicObject),GCC也能正常执行。

为什么public关键字影响GCC的行为?

这源于GCC对C++标准中dynamic_cast访问控制规则的实现细节:

  • C++中类的默认继承权限为private,原代码中Caterpillar是以私有继承方式继承HydrophobicObject的;
  • GCC的实现逻辑认为,当虚基类Body存在多条继承路径到Caterpillar时,若其中一条路径(Body <- HydrophobicObject <- Caterpillar)是私有继承,会导致外部上下文(如main函数)无法完整访问对象的继承结构信息,进而无法确认Body&引用的对象包含OwnerProtection子对象,因此触发bad_cast;
  • 当将HydrophobicObject的继承改为public后,所有从Body到Caterpillar的路径都变为可访问,GCC可以正常遍历继承结构、确认OwnerProtection子对象的存在,转换自然成功。

哪款编译器的行为符合C++标准?

根据C++标准的相关规定:

  1. 对于交叉类型的dynamic_cast(从一个基类引用转换到同一对象的另一个基类引用),只要目标基类是完整对象类型的可访问基类,且源基类到完整对象的路径可访问,转换就应当成功;
  2. 标准明确指出,基类的可访问性不影响dynamic_cast的格式合法性,但转换成功的前提是目标类型相对于完整对象是可访问的。

回到示例代码:

  • OwnerProtection是Caterpillar的public基类,属于可访问范畴;
  • Body到Caterpillar的路径中,Body <- ControlledObject <- CrawlingObject <- Caterpillar这条public继承路径完全可访问,即便存在另一条私有继承路径,也不影响确认对象的完整类型及OwnerProtection子对象的存在。

因此,Clang的行为符合C++标准,GCC的行为属于实现层面的严格化处理,不符合标准要求。

内容的提问来源于stack exchange,提问作者John Tracid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 22:24:55