首页 > 编程笔记

C++ try catch捕获异常详解

异常处理是许多现代编程语言中不可或缺的一部分,C++ 也不例外。通过使用 throw、try 和 catch 关键字,C++ 为程序员提供了强大的异常处理机制。

在这篇文章中,我们专门讲解 try 和 catch 的用法,并通过实例代码来详细解释。

C++ try

如果某个函数内抛出一个异常,系统将在异常抛出的同时退出函数。如果不想在异常抛出时退出函数,可在函数内创建一个特殊块用于捕获这个异常并处理错误。这个块就是 try 块。

try 块由关键字 try 引导,其通用语法形式是:
try{
    // 可能产生异常的代码块
}
可能产生异常的代码必须放在 try 块的里面,放在 try 块外面的代码产生的异常不能被该 try 块所捕获。

C++ catch

一旦 try 块内的代码发生异常,程序会跳转到与之对应的 catch 块。catch 块中的参数列表只能有一个参数,用于匹配 try 块内发生了哪种异常。

catch 块的语法格式如下:
catch(异常类型 异常值)
{
    // 处理异常的代码块
}
一个 try 块可以对应多个 catch 块,用于处理各种不同类型的异常。catch 块紧挨着 try 块,其语法形式为:
try{
    // 可能产生异常的代码块
}
catch(异常类型1 异常值1)
{
    // 处理异常的代码块
}
catch(异常类型2 异常值2)
{
    // 处理异常的代码块
}
...
C++ 规定,一个 try 后面至少有一个 catch 块。一旦 try 块内的代码发生异常,编译器会按照顺序依次匹配各个 catch 块,找到相匹配的 catch 块后,会执行 catch 块内部的代码,进而处理该异常。处理完异常后,编译器会继续执行后续的代码。

在查找匹配 catch 块期间,找到的 catch 块不一定是与异常最匹配的那个 catch 块,相反会选中第一个可以处理该异常的 catch 块。

捕获全部异常

当不能确定所有异常的类型的时候,可以捕获全部异常,代码如下:
catch (...) {
    // 处理异常的代码块
}
在这里用来表示所有的异常,可以跟所有的异常类型匹配。注意,在这种情况下捕获的异常,无法知道异常的类型,也无法得到异常对象。
catch(…)可以捕获所有的异常,是应用范围最广的异常处理方法,因此通常将它放置在所有 catch 块的后面。

实例演示

#include <iostream>
#include <stdexcept> // for std::runtime_error

void riskyFunction(int choice) {
    if (choice == 1) {
        throw 42; // 抛出 int 类型异常
    }
    else if (choice == 2) {
        throw "String type exception"; // 抛出 const char* 类型异常
    }
    else {
        throw std::runtime_error("Standard exception"); // 抛出 std::runtime_error 类型异常
    }
}

int main() {
    try {
        riskyFunction(2);
    }
    catch (int e) {
        std::cout << "Caught an integer exception: " << e << std::endl;
    }
    catch (const char* e) {
        std::cout << "Caught a string exception: " << e << std::endl;
    }
    catch (const std::runtime_error& e) {
        std::cout << "Caught a standard exception: " << e.what() << std::endl;
    }

    return 0;
}
运行结果为:

Caught a string exception: String type exception

函数 riskyFunction() 根据传入的 choice 参数,可能会抛出三种类型的异常:int、const char* 或 std::runtime_error。在 main() 函数的 try 块中,我们捕获这些异常并处理它们。

总结

通过使用 try 和 catch,我们可以写出更加健壮的程序,有效地处理可能发生的各种运行时错误。这不仅使程序更容易维护,而且提高了用户体验,因为程序可以提供更具描述性的错误消息,而不是突然崩溃。

推荐阅读