异常处理章节小结与测验

章节回顾

异常处理提供了一种机制,将错误或异常情形的处理与常规控制流解耦。这使开发者能够在恰当的时间和位置灵活地处理错误,从而消除(或极大缓解)返回码所带来的混乱。

  • throw 语句用于抛出异常。
  • try 块监视其内部或所调用代码抛出的异常。
  • catch 块捕获匹配类型的异常并进行处理;默认情况下,被捕获的异常即视为已处理。
  • 异常被立即处理:一旦抛出,控制流跳转到最近的 try 块并寻找匹配的 catch;若找到,则回卷栈并继续执行;若找不到,程序调用 std::terminate 并报告未处理异常。
  • 任意数据类型(包括类)均可作为异常抛出。
  • catch 可指定类型捕获,亦可用省略号 ... 作为通配处理器。捕获基类引用的处理器也会捕获派生类异常。
  • 标准库抛出的所有异常均派生自 <exception> 头文件中的 std::exception;捕获 std::exception& 即可捕获全部标准库异常,并通过 what() 获取异常描述。
  • catch 块内可抛出新异常(不会被自身捕获),亦可使用无操作数的 throw; 重新抛出原异常;切勿用捕获的异常变量再次抛出,否则会发生对象切片。
  • 函数 try 块允许捕获整个函数体或成员初始化列表中抛出的异常,主要用于派生类构造函数。
  • 绝不可在析构函数中抛出异常。
  • noexcept 说明符可用于声明函数的不抛/不失效保证。
  • std::move_if_noexcept 在对象拥有 noexcept 移动构造时返回可移动右值,否则返回可复制左值,以此在强异常保证前提下优先使用移动语义,否则退回复制。
  • 异常处理存在开销:通常使代码略慢,且异常触发时代价极高。异常应仅用于处理“异常”情形,而非常规错误(如输入无效)。

章节测验

编写一个 Fraction 类,其构造函数接受分子与分母。若用户传入 0 作为分母,抛出 std::runtime_error 异常(需包含头文件 <stdexcept>)。在主程序中,提示用户输入两个整数。若分数有效,输出该分数;若无效,捕获 std::exception 并提示用户分母无效。

一次示例运行:

Enter the numerator: 5
Enter the denominator: 0
Invalid denominator

关注公众号,回复"cpp-tutorial"

可领取价值199元的C++学习资料

公众号二维码

扫描上方二维码或搜索"cpp-tutorial"