0

0

c++怎么实现自定义异常类_c++ 继承std::exception与what方法重写【实战】

冰火之心

冰火之心

发布时间:2025-12-27 17:17:02

|

792人浏览过

|

来源于php中文网

原创

继承 std::exception 时必须用类内 std::string 成员保存错误消息并重写 const noexcept 的 what() 方法,否则 what() 返回悬垂指针导致未定义行为;还需显式声明 virtual 析构函数,并以 const& 方式捕获异常。

c++怎么实现自定义异常类_c++ 继承std::exception与what方法重写【实战】

为什么继承 std::exception 不能只写空构造函数

直接继承 std::exception 并只定义一个空构造函数,会导致 what() 返回的字符串不可控甚至崩溃。因为 std::exception 的默认实现不保存任何消息,其 what() 返回的是未定义行为(常见为指向已销毁内存的指针),尤其在抛出后被多次调用时极易出错。

  • 必须确保 what() 返回的 C 字符串生命周期长于异常对象本身存活期
  • 不能返回局部 std::string::c_str() 或临时 std::string 的内部指针
  • 推荐在类内持有一个 std::string 成员,用它来提供稳定地址

如何安全重写 what() 方法(含 const 和 noexcept)

what() 必须声明为 const noexcept,否则无法通过 std::exception 接口被正确调用;同时返回类型必须是 const char*,且指向的内容不能随对象析构而失效。

class FileOpenError : public std::exception {
private:
    std::string message_;
public:
    explicit FileOpenError(const std::string& file)
        : message_("Failed to open file: " + file) {}
const char* what() const noexcept override {
    return message_.c_str();
}

};

  • message_ 是类内 std::string 成员,保证字符串存储在堆上、生命周期与异常对象一致
  • noexcept 是强制要求:C++ 标准规定 std::exception::what()noexcept,子类重写也必须保持相同异常规范
  • 不要在 what() 里拼接新字符串或调用可能抛异常的函数

要不要加 virtual 析构函数?

要。虽然 std::exception 的析构函数已是 virtual,但显式写出能避免误删派生类资源(比如你后续在自定义异常中添加了动态分配的缓冲区或文件句柄)。

Faceswap
Faceswap

免费开源的AI换脸工具

下载

立即学习C++免费学习笔记(深入)”;

  • 即使当前没资源要清理,也建议统一加virtual ~FileOpenError() = default;
  • 不加不会立即报错,但若未来扩展异常类携带资源,就容易发生析构不完整、内存泄漏等问题
  • 所有多态基类都应该有 virtual 析构函数——这是 C++ 基本守则,不是可选项

实际使用时容易忽略的细节

捕获时别用值传递,也别漏掉 const&;日志打印前先确认 what() 是否真的可用;跨 DLL 边界抛异常需格外小心。

  • 错误写法:catch (FileOpenError e) —— 触发不必要的拷贝,还可能切片(如果从更深层派生)
  • 正确写法:catch (const FileOpenError& e)catch (const std::exception& e)
  • catch 块里直接用 e.what() 是安全的,但不要把它存成裸指针长期持有
  • Windows 下若异常跨越 DLL 边界(如 DLL 抛出、EXE 捕获),std::exception 及其派生类可能因 ABI 不兼容而崩溃;此时应改用错误码或跨 ABI 的结构体传信息

标准库异常体系不鼓励深度继承,但只要守住 what() 的生命周期、noexcept 约束和虚析构这三点,自定义异常就能稳住。最常翻车的地方,其实是把 what() 写成返回临时字符串的指针——这个坑,几乎每个初学者都踩过一次。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

311

2023.08.02

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

14

2025.11.27

java多态详细介绍
java多态详细介绍

本专题整合了java多态相关内容,阅读专题下面的文章了解更多详细内容。

14

2025.11.27

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

517

2023.09.20

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

246

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

204

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1429

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

606

2023.11.24

ip地址修改教程大全
ip地址修改教程大全

本专题整合了ip地址修改教程大全,阅读下面的文章自行寻找合适的解决教程。

27

2025.12.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PostgreSQL 教程
PostgreSQL 教程

共48课时 | 6.1万人学习

Excel 教程
Excel 教程

共162课时 | 9.7万人学习

PHP基础入门课程
PHP基础入门课程

共33课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号