为何从引用进行dynamic_cast会导致段错误?
问题根源:函数声明顺序错误导致无限递归栈溢出
你的代码出现段错误的核心原因是函数重载的声明顺序问题:在定义to_string(expr_t&)时,to_string(ident_t&)还没有被声明,编译器无法识别这个重载版本。当你在to_string(expr_t&)里调用to_string(*id)时,ident_t&会被隐式转换为expr_t&,从而递归调用to_string(expr_t&),形成无限递归,最终导致栈溢出(段错误)。
修复方案
方案1:提前声明重载函数
在to_string(expr_t&)的定义之前,先声明to_string(ident_t&),让编译器知道这个重载版本:
#include <iostream> #include <string> struct expr_t { virtual ~expr_t() {} }; struct ident_t : public expr_t { std::string name; ident_t(std::string name) : name(name) {} }; // 提前声明重载函数 std::string to_string(ident_t&); std::string to_string(expr_t& v) { if (auto* id = dynamic_cast<ident_t*>(&v)) { return to_string(*id); // 现在编译器能找到正确的重载 } return "error"; } std::string to_string(ident_t& v) { return v.name; } int main() { expr_t* b = new ident_t("c"); std::cout << to_string(*b) << std::endl; // 输出 "c" delete b; return 0; }
方案2:使用多态(更符合面向对象设计)
既然已经用了虚析构函数,不如把字符串转换逻辑做成虚函数,放在基类中,这样更简洁也避免了重载顺序问题:
#include <iostream> #include <string> struct expr_t { virtual ~expr_t() {} virtual std::string to_string() const = 0; // 纯虚函数 }; struct ident_t : public expr_t { std::string name; ident_t(std::string name) : name(name) {} std::string to_string() const override { return name; } }; int main() { expr_t* b = new ident_t("c"); std::cout << b->to_string() << std::endl; // 输出 "c" delete b; return 0; }
内容的提问来源于stack exchange,提问作者Pluveto
相关产品推荐
相关产品推荐

