目录

  1. 异常处理概述
  2. 异常处理的基本语法
  3. 抛出异常(throw)
  4. 捕获异常(try-catch)
  5. 异常的层次结构
  6. 自定义异常类型
  7. 异常规范
  8. 示例代码
  9. 参考资料

1. 异常处理概述

C++ 异常处理机制允许程序在运行时出现错误时不立即终止,而是通过捕获和处理异常来恢复程序的正常执行。异常处理提供了一种优雅的错误处理方法,使得程序在发生异常时能够进行适当的处理并保持稳定性。

C++ 中的异常处理使用 trycatchthrow 关键字来实现:

  • throw:用于抛出异常。
  • try:用于定义一个代码块,C++ 会在该代码块内检测异常。
  • catch:用于捕获异常并处理。

通过使用异常机制,程序员可以捕获程序中的错误并采取相应的措施,而不需要通过繁琐的错误代码来进行错误检查。


2. 异常处理的基本语法

C++ 的异常处理机制依赖于 trycatch 语句。throw 语句用于抛出异常,catch 语句用于捕获异常。

基本结构

try {
    // 可能会抛出异常的代码
    throw exception;  // 抛出异常
}
catch (ExceptionType1& e) {
    // 处理异常类型1
}
catch (ExceptionType2& e) {
    // 处理异常类型2
}

try 块中,程序执行可能会抛出异常。如果抛出异常,程序会跳到对应的 catch 块进行异常处理。


3. 抛出异常(throw)

throw 关键字用于抛出异常。异常可以是系统提供的内建异常类型,也可以是用户自定义的异常类型。异常对象通常是通过构造函数创建的。

语法

throw exception_object;

例如,抛出一个标准异常:

throw std::runtime_error("An error occurred!");

也可以抛出自定义类型的异常:

class MyException {
public:
    const char* message;
    MyException(const char* msg) : message(msg) {}
};
throw MyException("My custom exception");


4. 捕获异常(try-catch)

try 块中,可能发生的异常会被抛出,而在 catch 块中进行捕获并处理。每个 catch 块都可以捕获不同类型的异常。

语法

try {
    // 代码逻辑
}
catch (const std::exception& e) {
    // 捕获标准异常并处理
}
catch (const MyException& e) {
    // 捕获自定义异常并处理
}

捕获所有异常

为了捕获所有类型的异常,可以使用捕获通用异常类型 ...,它会捕获所有未被前面 catch 捕获的异常。

catch (...) {
    std::cout << "An unexpected error occurred!" << std::endl;
}


5. 异常的层次结构

C++ 提供了标准的异常类型层次结构。所有的标准异常类都继承自 std::exception。以下是常见的异常类型:

  • std::exception:基类,用于捕获所有标准异常。
  • std::runtime_error:表示程序运行时的错误。
  • std::logic_error:表示程序逻辑错误。
  • std::bad_alloc:表示内存分配失败的异常。

示例

try {
    throw std::runtime_error("Runtime error occurred");
}
catch (const std::exception& e) {
    std::cout << "Exception: " << e.what() << std::endl;
}


6. 自定义异常类型

你可以创建自定义的异常类型,这些类型通常继承自 std::exception 或其他标准异常类。自定义异常类可以提供额外的信息或功能。

自定义异常类型示例

#include <iostream>
#include <stdexcept>

class MyException : public std::exception {
public:
    const char* what() const noexcept override {
        return "My custom exception occurred";
    }
};

int main() {
    try {
        throw MyException();
    }
    catch (const MyException& e) {
        std::cout << e.what() << std::endl;  // 输出自定义异常信息
    }
    return 0;
}


7. 异常规范

C++11 引入了异常规范,用于指定函数抛出异常的情况。在函数声明中,noexcept 关键字用于指明函数不抛出异常。

noexcept 示例

void myFunction() noexcept {  // 指明该函数不会抛出异常
    // 函数逻辑
}

如果一个函数声明为 noexcept,但是在函数内部抛出了异常,则会导致程序调用 std::terminate() 终止。


8. 示例代码

示例 1:基本异常处理

#include <iostream>
#include <stdexcept>

void divide(int a, int b) {
    if (b == 0) {
        throw std::invalid_argument("Division by zero");
    }
    std::cout << "Result: " << a / b << std::endl;
}

int main() {
    try {
        divide(10, 0);
    }
    catch (const std::invalid_argument& e) {
        std::cout << "Error: " << e.what() << std::endl;
    }
    return 0;
}

在这个示例中,我们定义了一个 divide 函数,它会抛出一个 std::invalid_argument 异常,表示除数为零时的错误。在 main 函数中,捕获并处理该异常。

示例 2:自定义异常

#include <iostream>
#include <exception>

class NegativeValueException : public std::exception {
public:
    const char* what() const noexcept override {
        return "Negative value error!";
    }
};

void checkValue(int value) {
    if (value < 0) {
        throw NegativeValueException();
    }
}

int main() {
    try {
        checkValue(-5);
    }
    catch (const NegativeValueException& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    return 0;
}

在这个示例中,我们定义了一个自定义异常 NegativeValueException,并在 checkValue 函数中检查值是否为负数,若是则抛出该异常。


9. 参考资料


总结

C++ 的异常处理机制提供了强大的错误处理能力,使得程序可以在运行时捕获和处理异常。通过 trycatchthrow,程序可以在发生错误时不中断执行,而是提供一种优雅的方式进行处理。自定义异常类型和异常层次结构使得程序员可以根据需求创建专门的异常类型,提高了程序的可维护性和可扩展性。在使用异常处理时,合理设计异常规范和捕获策略能够有效提升程序的稳定性和鲁棒性。