关于 try... catch

发布时间 2023-08-11 15:36:58作者: strive-sun

在逛论坛看见一个有意思的帖子,有点意思,记录下

一些我觉得有用的回复,放到下面了,

1. 当某些错误状况难以完全避免时,try-catch 可以用来控制错误扩散范围,防止整个程序崩溃。比如外部系统异常、网络中断等不可控因素。

2. 对于业务逻辑复杂的情况,想要全面预测并避免所有错误是很困难的。try-catch 可以用来处理意料之外的异常状况。

3. try-catch 允许将错误处理与业务逻辑代码解耦,使主要逻辑更简洁清晰。合理使用也可以使程序结构更灵活。

4. 对于一些开发者不可修改的第三方代码,try-catch 可能是处理潜在错误的最佳手段。

所以,try-catch 更多是作为最后的“安全网”,并不是用来代替前置的输入校验和状态检测。合理的方法是状态检测与 try-catch 共同使用,使程序既健壮又能优雅地处理边界情况。总之,try-catch 并不是万金油,还需要开发者理性判断其适用场景。

 

当然,我们最好可以看看标准委员会成员对此问题的回答,

原文:

What good can using exceptions do for me? The basic answer is: Using exceptions for error handling makes your code simpler, cleaner, and less likely to miss errors. But what’s wrong with “good old errno and if-statements”? The basic answer is: Using those, your error handling and your normal code are closely intertwined. That way, your code gets messy and it becomes hard to ensure that you have dealt with all errors (think “spaghetti code” or a “rat’s nest of tests”).

机翻:

使用异常来进行错误处理有哪些好处呢?基本的回答是:使用异常来进行错误处理可以使你的代码更简洁、更清晰,且不太容易漏掉错误。但是,使用“老式的 errno 和 if 语句”有什么问题呢?基本的回答是:使用这种方式,你的错误处理代码和普通代码会紧密交织在一起。这样会让你的代码变得混乱,很难确保你已经处理了所有的错误(类似“代码逻辑混乱”或“错综复杂的测试条件”)


拓展:

try... catch 能捕获哪些异常以及无法捕获哪些异常呢?

"无法捕获的异常"指的是在C++的异常处理机制中,某些异常在被抛出时,即使使用try-catch语句也无法被正常捕获,通常会导致程序终止、崩溃或无法继续执行。这些无法捕获的异常通常是由于某些特定的情况触发,例如硬件故障、操作系统限制、编程错误等。下面是一些可能会导致无法捕获异常的情况:

  1. 访问越界: 如果在数组访问中发生越界,例如访问一个不存在的数组元素,会导致无法捕获的异常。这可能触发操作系统的保护机制,导致程序被终止。

  2. 空指针引用: 当使用空指针(nullptr)访问对象的成员或者调用成员函数时,会触发空指针异常,这也是一种无法捕获的异常。

  3. 栈溢出: 当递归深度过大或者函数调用层级过多时,可能导致栈溢出异常,这通常会导致程序崩溃。

  4. 硬件故障: 例如除以零、硬件错误、非法指令等,这些异常可能会导致程序无法继续执行。

  5. 使用 abort 函数: 如果在程序中调用了abort函数,它会立即终止程序运行,不会触发C++异常处理机制。

"可以捕获的异常"指的是在C++的异常处理机制中,一些异常可以通过try-catch语句被捕获并进行处理,从而避免程序的终止或崩溃。这些异常通常是由于特定情况的错误或异常情况而抛出的,例如在函数中使用throw语句抛出的异常,或者由标准库中的异常类抛出的异常。

以下是一些常见可以捕获的异常的示例以及如何使用 try-catch来捕获和处理它们:

1. 自定义异常: 开发者可以自定义异常类,通常继承自 std::exception 或其子类,然后在需要的地方使用 throw 语句抛出这些自定义异常。

#include <iostream>
#include <stdexcept>

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

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

2. 标准库异常: C++标准库提供了一些异常类,例如std::runtime_errorstd::logic_error等,可以在需要时抛出,然后通过try-catch捕获和处理。

#include <iostream>
#include <stdexcept>

int main() {
    try {
        throw std::runtime_error("Standard exception");
    } catch (const std::exception& e) {
        std::cout << "Caught exception: " << e.what() << std::endl;
    }
    return 0;
}

3. 函数可能抛出的异常: C++中的函数可以在其声明中指定可能抛出的异常类型,调用这些函数时,编译器会提示你可能需要捕获这些异常。

#include <iostream>
#include <stdexcept>

void foo() {
    throw std::runtime_error("Exception from foo()");
}

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

  

注意,在捕获异常时,通常使用基类类型(如 const std::exception&)来捕获异常,这样可以捕获各种不同类型的异常,而不需要为每一种异常都编写特定的 catch 块。这种做法也符合异常处理的最佳实践。