C++中如何检测dynamic_cast结果 避免触发段错误
解决方案
问题根因
你遇到的段错误本质是dynamic_cast指针转换失败时会返回nullptr,直接解引用空指针就会触发崩溃,只要在转换前校验返回值或者提前做类型匹配校验就能解决。
方案1:直接校验dynamic_cast返回值(无侵入修改原类)
这是最不需要改现有代码的方案,每次转换后先判断返回值是否为空即可:
#include <stdexcept> void test() { base *p = new derived<float>(); // 合法转换场景 if (auto* derived_float = dynamic_cast<derived<float>*>(p)) { derived_float->save(1); } else { throw std::runtime_error("类型转换失败:目标类型与实际实例类型不匹配"); } // 非法转换场景 if (auto* derived_int = dynamic_cast<derived<int>*>(p)) { derived_int->save(1); } else { throw std::runtime_error("类型转换失败:目标类型与实际实例类型不匹配"); } }
方案2:基类新增类型校验接口(封装校验逻辑)
如果不想每次调用都写重复的判断逻辑,可以在基类新增虚接口暴露类型信息,自动完成校验,完全符合你要在调用save时自动校验类型的需求:
改造后的类实现
#include <typeinfo> #include <stdexcept> #include <string> class base { public: virtual ~base() = default; // 新增虚函数返回实际派生类绑定的类型信息 virtual const std::type_info& get_actual_type() const = 0; // 封装通用save接口,内部自动校验类型 template<typename T> void save(T value) { if (get_actual_type() != typeid(T)) { throw std::runtime_error("save类型不匹配:预期类型为" + std::string(get_actual_type().name()) + ",传入类型为" + typeid(T).name()); } static_cast<derived<T>*>(this)->save(value); } }; template <typename T> class derived : public base { T a; friend class base; // 允许基类访问私有save方法 public: const std::type_info& get_actual_type() const override { return typeid(T); } void save(T a_) { a = a_; } };
调用方式
改造后不需要用户手动做类型转换,直接调用基类的save接口即可,类型不匹配会自动抛异常:
void test() { base *p = new derived<float>(); p->save(1.0f); // 类型匹配,正常执行 p->save(1); // 类型不匹配,直接抛出异常,不会触发段错误 delete p; }
注意:如果存在除derived<T>之外的其他类继承base,需要额外加逻辑校验派生类类型,避免static_cast转换出错
无RTTI场景适配
如果你的项目关闭了RTTI不能用typeid,可以自己实现静态类型标识替换typeid:
// 生成唯一类型ID inline int generate_type_id() { static int id = 0; return id++; } template<typename T> int get_type_id() { static int id = generate_type_id(); return id; }
把基类的get_actual_type返回值改成int,派生类返回get_type_id<T>(),对比逻辑改成判断ID是否相等即可。
内容的提问来源于stack exchange,提问作者陈泽霖
相关产品推荐
相关产品推荐

