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

为何使用dynamic_cast转换时始终抛出std::bad_cast异常?

问题原因:对象切片(Object Slicing)

你的代码核心问题是对象切片:tag.children是std::vector<Tag>类型,存储的是Tag对象实例。当你把TagName或TagValue对象通过push_back存入这个容器时,只会复制对象中的基类Tag部分,派生类独有的成员(比如TagName::name、TagValue::value)会被"切掉",最终容器里存储的都是纯Tag对象,而非你原本的TagName/TagValue对象。

这就导致后续调用dynamic_cast时,实际操作的对象是Tag类型,根本不是TagName或TagValue,自然会触发std::bad_cast异常——因为dynamic_cast只能在有继承关系的多态对象间合法转换,而这里的对象已经被切片成基类实例了。

修复方案

要解决这个问题,你需要存储指向基类的指针(或智能指针),而不是直接存储基类对象,这样才能保留派生类的完整信息。比如改用std::vector<std::unique_ptr<Tag>>作为容器:

#include <memory> // 引入智能指针头文件

struct Attribute
{
    std::string key{};
    std::string value{};
};

struct Tag
{
    Tag* parent{};
    std::vector<std::unique_ptr<Tag>> children{}; // 修改为智能指针容器
    virtual void Dummy() {};
};

struct TagName : public Tag
{
    std::string name{};
    std::vector<Attribute> attributes{};
    void Dummy() override {};
};

struct TagValue : public Tag
{
    std::string value;
    void Dummy() override {};
};

int main()
{
    Tag tag{};
    
    auto tn = std::make_unique<TagName>();
    tn->name = "html";
    tn->attributes.push_back({"color", "black"});
    tag.children.push_back(std::move(tn));    // 存入智能指针

    auto tv = std::make_unique<TagValue>();
    tv->value = "lorepsum";
    tag.children.push_back(std::move(tv));    // 存入智能指针

    std::cout << tag.children.size() << std::endl;

    TagName& name = dynamic_cast<TagName&>(*tag.children.at(0));
    TagValue& val = dynamic_cast<TagValue&>(*tag.children.at(1));

    // 验证转换成功
    std::cout << name.name << std::endl; // 输出html
    std::cout << val.value << std::endl; // 输出lorepsum

    return 0;
}

这样容器里存储的是指向派生类对象的智能指针,对象的多态性得以保留,dynamic_cast就能正确识别对象的实际类型并完成转换。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 18:22:34