C++ 中的异常处理

原文:https://www.studytonight.com/cpp/exception-handling-in-cpp.php

错误可以大致分为两种类型。我们将逐一讨论。

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

编译时错误–编译时捕获的错误称为编译时错误。编译时错误包括库引用、语法错误或不正确的类导入。

运行时错误 -它们也被称为异常。运行时捕获的异常会产生严重的问题。

错误阻碍程序的正常执行。异常处理是以不妨碍系统正常执行的方式处理错误和异常的过程。例如,用户将一个数字除以零,这将编译成功,但会出现异常或运行时错误,这将导致我们的应用程序崩溃。为了避免这种情况,我们将在代码中引入异常处理技术。

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

  • 尝试
  • 捕捉

语法:

try
{
    //code
    throw parameter;
}
catch(exceptionname ex)
{
    //code to handle exception
}

try区块

可以抛出任何异常的代码被保存在try块中。然后,当代码将导致任何错误时,该错误/异常将被捕获在catch块中。

catch区块

catch块旨在捕获错误并处理异常情况。我们可以有多个 catch 块来处理不同类型的异常,并在异常发生时执行不同的操作。例如,我们可以显示描述性消息来解释发生任何特定异常的原因。

throw声明

它用于向异常处理程序抛出异常,即用于传递有关错误的信息。throw表达式接受一个参数,并将该参数传递给处理程序。

throw语句用于当我们明确希望发生异常时,那么我们可以使用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 block activates exception handling
    try 
    {
        if(b == 0)
        {
            // throw custom exception
            throw "Division by zero not possible";
            c = a/b;
        }
    }
    catch(char* ex) // catches exception
    {
        cout<<ex;
    }
    return 0;
}

除以零是不可能的

在上面的代码中,我们正在检查除数,如果它为零,我们将抛出一个异常消息,然后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)
                // throwing numeric value as exception
                throw ex;
            else
                // throwing a character as exception
                throw 'ex';
        } 
        catch (int ex)  // to catch numeric exceptions
        {
            cout << "Integer exception\n";
        } 
        catch (char ex) // to catch character/string exceptions
        {
            cout << "Character exception\n";
        }
    }
}

整数异常字符异常

上面的程序不言而喻,如果数组x中整数的值小于 0,我们抛出一个数值作为异常,如果值大于 0,那么我们抛出一个字符值作为异常。我们有两个不同的catch块来捕捉这些异常。


C++ 中的广义catch

下面的程序包含一个通用的catch块来捕获任何未捕获的错误/异常。catch(...) block 处理所有类型的异常。

#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';
        } 
        // generalised catch block
        catch (...) 
        {
            cout << "Special exception\n";
        }
    }
return 0;
}

特殊例外特殊例外

在上面的例子中,两个异常都被一个单独的catch块捕获。我们甚至可以有单独的catch块来处理整数和字符异常,以及通用的catch块。


C++ 中的标准异常

下的 C++ 中有一些标准的异常,我们可以在程序中使用。它们排列在父子类层次结构中,如下所示:

  • std::exception -所有标准 C++ 异常的父类。
  • 逻辑 _ 错误 -程序内部逻辑发生异常。
    • 域 _ 错误 -使用无效域导致异常。
    • 无效参数 -因无效参数导致异常。
    • 超出范围 -超出范围导致异常,即大小要求超过分配。
    • 长度 _ 误差 -长度误差导致异常。
  • 运行时 _ 错误 -运行时发生异常。
    • 范围 _ 错误 -由于内部计算中的范围错误而导致异常。
    • 溢出 _ 错误 -算术溢出错误导致异常。
    • 下溢 _ 错误 -由于算术下溢错误导致的异常
  • bad_alloc -使用 new()分配内存失败时出现异常。
  • bad_cast -动态 cast 失败时出现异常。
  • bad_exception - Exception 是专门设计在动态异常说明符中列出的。
  • 坏 _ type id-type id 抛出异常。