异常是指在程序执行期间发生的意外或异常情况,比如除以零、访问无效的内存地址等。这些异常可能导致程序崩溃或产生错误结果。
异常处理是C 中一种用于处理程序运行过程中出现错误或异常情况的机制。通过使用异常处理,可以使程序在发生异常时进行适当的处理,而不是直接导致程序崩溃。
①异常类型(Exception Types)
C 中的异常以不同的类型表示,通常以类的形式存在。标准库提供了一些常见的异常类,如std::exception、std::runtime_error等,同时也可以自定义异常类来表示特定的异常类型。
在C 中,可以使用标准库提供的异常类,也可以自定义异常类。以下是一些常见的异常类:
std::exception:这是C 标准库中定义的最通用的异常类。其他所有异常类都应该派生自该类。它提供了一个what()成员函数,用于返回异常的描述信息。
std::bad_alloc:当内存分配失败时,会抛出该异常。通常在使用new运算符分配内存时可能会出现。
std::runtime_error:表示运行时错误的异常类,它包括了一些逻辑上的错误,例如除数为零、索引越界等。
std::logic_error:表示逻辑错误的异常类,它包括一些开发者错误,例如调用了错误的函数、传递了无效的参数等。
std::out_of_range:当使用容器或数组时,如果索引超出范围,就会抛出该异常。
std::invalid_argument:当传递了无效的参数时,会抛出该异常。
std::overflow_error和std::underflow_error:当算术操作导致溢出或下溢时,会抛出这两个异常。
std::bad_cast:当使用dynamic_cast进行类型转换失败时,会抛出该异常。
②异常抛出(Throwing Exceptions)
当程序发生异常情况时,可以使用throw
语句来抛出异常对象。throw
后面跟着要抛出的异常对象,可以是任何类型的对象,包括预定义的异常类或自定义的异常类的对象。
throw MyException("Something went wrong.");
③异常捕获(Catching Exceptions)
使用try-catch
语句块来捕获并处理异常。try
块中包含可能会引发异常的代码,而catch
块则用于处理捕获到的异常。
try {
// 可能引发异常的代码
} catch (ExceptionType1& e1) {
// 处理类型为 E1 的异常
} catch (ExceptionType2& e2) {
// 处理类型为 E2 的异常
} catch (...) {
// 处理其他类型的异常
}
注意,catch
块可以有多个,并根据捕获到的异常的类型进行匹配,只有与异常类型匹配的catch
块会被执行。
④异常传播(Exception Propagation)
当一个异常在函数内部引发但未被捕获时,它将传播到调用该函数的地方。如果没有在调用堆栈中的任何函数中处理该异常,程序将终止并显示异常消息。
⑤异常处理顺序(Order of Exception Handling)
在try-catch
语句块中,应该按照从具体到一般的顺序排列catch
块。也就是说,应该首先捕获最具体的异常,然后再逐渐向上捕获更一般的异常。
⑥异常声明(Exception Specifications)
C 11之前,可以使用异常声明来指定函数可能抛出的异常类型。但在C 11中,异常声明已被弃用,取而代之的是使用noexcept
和异常规范(exception specification)来指定函数是否可能抛出异常。
// 弃用的异常声明
void foo() throw(ExceptionType);
// C 11 异常规范
void bar() noexcept;
⑦标准异常(Standard Exceptions)
C 标准库中定义了一些常见的异常类,可在程序中使用。例如,std::exception
是所有标准异常类的基类,它提供了一个描述异常的what()
方法。
try {
// 可能引发异常的代码
} catch (const std::exception& e) {
std::cout << "Exception caught: " << e.what() << std::endl;
}