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

为何从引用进行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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:57:26