为何使用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_
相关产品推荐
相关产品推荐

