C++ 异常处理



C++中的异常处理

错误可以分为两类:

  1. 编译时错误
  2. 运行时错误

编译时错误 – 在编译时发生的错误称为编译时错误,编译时错误包括库引用、语法错误。 运行时错误 - 也称为异常,在运行时捕获的异常会产生严重的问题。

异常会阻碍程序的正常执行,异常处理是在保证程序正常运行的情况下处理错误和异常的过程,例如,用户将一个数字除以零,虽然会成功编译,但会发生异常,导致我们的应用程序崩溃,为了避免这种情况,我们将在代码中使用异常处理。

在 C++ 中,异常处理是使用三个关键字完成的:

  • try
  • catch
  • throw

语法:

try
{
    //保护代码
    throw 表达式;
}
catch(异常类型)
{
    //处理异常的代码
}


try

可能抛出异常的代码写入在try 块中,然后,当代码发生错误时,该错误或异常将在 catch 块中被捕获。



catch

catch 块用来捕获异常并处理,我们可以有多个 catch 块来处理不同类型的异常,并执行不同的操作。



throw 语句

它用于向catch块抛出异常,即它用于传达有关错误的信息, throw 语句的操作数可以是任意的表达式,表达式的结果的类型决定了抛出的异常的类型。



通过示例来理解

让我们通过一个简单的例子来理解try、catch和throw的用法。

下面的程序编译成功,但程序在运行时失败,导致异常。

#include <iostream>
#include<conio.h>
using namespace std;
int main()
{
    int a=10,b=0,c;
    c=a/b;
    return 0;
}

上面的程序能编译通过,但在运行时会崩溃,因为我们试图用 0 来除一个数,这是不可能的。

如何处理这种情况?我们可以使用异常处理,并且可以通过显示消息来通知用户不能将数字除以零。



使用 trycatchthrow 语句

现在我们加入异常处理。

#include <iostream>
#include<conio.h>
using namespace std;
int main()
{
    int a=10, b=0, c;
    try 
    {
        if(b == 0)
        {
            // 抛出异常表达式
            throw "0不能作除数";
            c = a/b;
        }
    }
    catch(char* ex) 
    {
        cout<<ex;
    }
    return 0;
}

以上实例输出结果:

0不能作除数

在上面的代码中,我们检查除数,如果它为零,我们将抛出异常消息,然后 catch 块捕获该异常并打印消息。

这样做程序不会崩溃,用户只会看到消息“0不能作除数”,这就是我们使用异常处理的原因。



使用多个 catch

下面的程序包含多个 catch 块,以不同的方式处理不同类型的异常。

#include <iostream>
#include<conio.h>
using namespace std;

int main()
{
    int x[3] = {-1,2};
    for(int i=0; i<2; i++)
    {
        int ex = x[i];
        try 
        {
            if (ex > 0)
                // 抛出数字
                throw ex;
            else
                // 抛出字符
                throw 'ex';
        } 
        catch (int ex)  // 用于捕获int类型
        {
            cout << "数字异常\n";
        } 
        catch (char ex) // 用于捕获字符或字符串
        {
            cout << "字符异常\n";
        }
    }
}

以上实例输出结果:

数字异常
字符异常

上面的示例中,如果数组x中的整数值小于0,我们抛出一个数字作为异常,如果值大于0,那么我们抛出一个字符值作为异常,然后我们有两个不同的 catch 块来捕获这些异常。

C++ 中的通用 catch

下面的示例包含一个通用的 catch 块来捕获所有的异常,catch(...) 块负责处理所有类型的异常。

#include <iostream>
#include<conio.h>
using namespace std;

int main()
{
    int x[3] = {-1,2};
    for(int i=0; i<2; i++)
    {
        int ex=x[i];
        try 
        {
            if (ex > 0)
                throw ex;
            else
                throw 'ex';
        } 
        // 通用异常处理
        catch (...) 
        {
            cout << "异常处理\n";
        }
    }
return 0;
}

以上实例输出结果:

异常处理
异常处理

在上面的例子中,两个异常都被一个 catch 块捕获。

C++ 中的标准异常

<exception> 下的 C++ 中有一些标准异常,我们可以在程序中直接使用它们,如下所示:

  • std::exception - 所有标准 C++ 异常的父类。
  • logic_error - 异常发生在程序的内部逻辑中。
    • domain_error - 由于使用无效域而导致的异常。
    • invalid argument - 由于参数无效而导致的异常。
    • out_of_range - 超出范围导致的异常,即大小要求超出分配。
    • length_error - 由于长度错误导致的异常。
  • runtime_error - 运行时发生异常。
    • range_error - 由于内部计算中的范围错误导致的异常。
    • overflow_error - 由于算术溢出错误导致的异常。
    • underflow_error - 由于算术下溢错误导致的异常
  • bad_alloc - 当使用 new() 分配内存失败时会发生异常。
  • bad_cast - 动态转换失败时发生异常。
  • bad_exception - 异常被专门设计为在动态异常说明符中列出。
  • bad_typeid - typeid 抛出的异常。