Skip to content

异常处理

程序错误通常分为两类:

  • 逻辑错误:由编程失误导致的错误,例如“索引超出范围”
  • 异常:超出程序的控制范围的错误条件,例如“网络服务不可用”、“内存不足”

许多编程语言都有对异常的处理,C++ 当然也不例外。

示例:

cpp
/**
 * Copyright 2023 <Hardworking Bee>
 */

#include <iostream>
#include <limits>
#include <stdexcept>

void Test(int n) {
  if (n > std::numeric_limits<char>::max()) {
    throw std::overflow_error("n is too large");
  }
}

int main() {
  try {
    Test(1000);
  } catch (const std::overflow_error& e) {
    std::cerr << e.what() << '\n';
    return -1;
  }

  return 0;
}

TIP

为了增强可读性和方便团队协作,如果函数内部可能抛出异常,建议声明异常类型。

cpp
void Test(int n) throw(std::overflow_error) {
  if (n > std::numeric_limits<char>::max()) {
    throw std::overflow_error("n is too large");
  }
}

自定义异常

在 C++ 中我们除了可以 throw 标准库已经定义了的异常,我们还可以 throw 任何类型,例如 throw -1throw "This is an exception"。但一般而言,我们建议 throwstd::exception 直接或间接继承的类型。

示例:

cpp
/**
 * Copyright 2023 <Hardworking Bee>
 */

#include <iostream>
#include <stdexcept>

class divide_error : public std::runtime_error {
 public:
  explicit divide_error(const std::string& msg) : std::runtime_error(msg) {}
};

class divide_by_zero : public divide_error {
 public:
  divide_by_zero() : divide_error("attempted to divide by zero") {}
};

int Divide(int a, int b) throw(divide_by_zero) {
  if (b == 0) {
    throw divide_by_zero();
  }
  return a / b;
}

int main() {
  try {
    Divide(1, 0);
  } catch (const divide_by_zero& e) {
    std::cerr << e.what() << '\n';
    return -1;
  }

  return 0;
}

std::runtime_error 继承 std::exception,表示运行时错误的异常。

References