捕捉异常

try/catch 块用于捕获异常。try 部分中的代码是可能抛出异常的代码,catch 子句中的代码处理异常。

#include <iostream>
#include <string>
#include <stdexcept>

int main() {
  std::string str("foo");
  
  try {
      str.at(10); // access element, may throw std::out_of_range
  } catch (const std::out_of_range& e) {
      // what() is inherited from std::exception and contains an explanatory message
      std::cout << e.what();
  }
}

多个 catch 子句可用于处理多种异常类型。如果存在多个 catch 子句,则异常处理机制会尝试按照它们代码中的出现顺序进行匹配 :

std::string str("foo");
  
try {
    str.reserve(2); // reserve extra capacity, may throw std::length_error
    str.at(10); // access element, may throw std::out_of_range
} catch (const std::length_error& e) {
    std::cout << e.what();
} catch (const std::out_of_range& e) {
    std::cout << e.what();
}

可以使用公共基类的单个 catch 子句捕获从公共基类派生的异常类。上面的例子可以用 std:exception 的单个子句替换 std::length_errorstd::out_of_range 的两个 catch 子句:

std::string str("foo");
  
try {
    str.reserve(2); // reserve extra capacity, may throw std::length_error
    str.at(10); // access element, may throw std::out_of_range
} catch (const std::exception& e) {
    std::cout << e.what();
}

因为 catch 子句是按顺序尝试的,所以一定要先编写更具体的 catch 子句,否则你的异常处理代码可能永远不会被调用:

try {
    /* Code throwing exceptions omitted. */
} catch (const std::exception& e) {
    /* Handle all exceptions of type std::exception. */
} catch (const std::runtime_error& e) {
    /* This block of code will never execute, because std::runtime_error inherits
       from std::exception, and all exceptions of type std::exception were already
       caught by the previous catch clause. */
}

另一种可能性是 catch-all 处理程序,它将捕获任何抛出的对象:

try {
    throw 10;
} catch (...) {
    std::cout << "caught an exception";
}