技术文章翻译(一) -- C++异常处理机制

本人声明

1.本栏仅为归档自己看到的优秀文章;
2.文章版权归原作者所有;
3.因为个人水平有限,翻译难免有错误,请多多包涵。

原文地址

https://www.codeguru.com/columns/kate/c-exception-handling-how-to-handle-exceptions-in-c.html

文章正文

C++异常处理机制

– 作者:Manoj Debnath 发表于:2017.03.24
异常是指不符合规则或者不符合常理的情况。它表示程序执行期间可能出现了问题。异常处理机制提供了一种方法,该方法能够将程序控制权和相关信息从程序执行点转移到异常处理的位置。处理程序为程序员提供了一个机会窗口,该窗口可以顺利地终止或以适当的方式处理异常。本文给出了C ++中实现异常处理机制的基本思路。

  • 概述

程序是从执行某项具体任务开始的。如果执行指定任务的代码顺利运行,则继续执行下一个任务,依此类推,直到程序完成全部功能。现在,如果在执行过程中出现任何错误,代码将会进入到错误处理例程。错误处理逻辑与正常的程序逻辑是混合在一起的,并且会交叉执行。虽然这种混合的形式很好,但它会使得代码变得难以阅读、维护和调试;即使对于规模不是很大的程序,这种情况也依然存在。

请注意,C语言中提供错误处理机制还是非常原始的。这是因为C语言本身对其没有直接的支持。因此,我们在这里只能采用比较低级的方式–通过函数返回值来判断。通常来说,如果函数返回负值或NULL,则表示函数发生了错误。有时候,我们会定义一个名为errno的全局变量,该变量作为函数调用期间的错误指示符。头文件error.h则定义了许多具体的错误代码。

使用异常处理机制,不仅可以提高程序的清晰度,而且能够利用异常处理和程序逻辑分离的方式来降低代码的复杂度。我们可以分别处理它们。这带来了巨大的灵活性;除此之外,我们可以决定处理哪些异常,并将它们按照相关类型分组处理,或者完全不进行处理。

  • C++中的异常处理机制
    C ++异常处理是包含在try … catch块中的。 try块包含着可能会发生异常的代码段。它跟在关键字try后的大括号里。如果发生异常,它将由专门捕获和处理异常的catch语句块处理。 catch也是一个关键字,后跟大括号。每个try块都至少附带一个紧跟其后的catch处理程序。一个try块也可能关联多个catch处理程序。在这种情况下,一旦发生异常时,程序会选择与其异常类型匹配的catch处理程序作为最终的处理程序。匹配是基于抛出的异常类型或者其继承的基类类型来进行的。

  • 下面的例子用于说明异常处理的基本思想:

#ifndef DIVISIONBYZEROEXCEPTION_H_
#define DIVISIONBYZEROEXCEPTION_H_

#include <stdexcept>
using namespace std;

class DivisionByZeroException :public runtime_error{
public:
   DivisionByZeroException():runtime_error
      ("divide by zero exception occurred"){};
};

#endif /* DIVISIONBYZEROEXCEPTION_H_ */


#include <iostream>
#include "DivisionByZeroException.h"
using namespace std;

double div(int num, int denom) {
   if (denom == 0)
      throw DivisionByZeroException();
   return static_cast<double>(num) / denom;
}

int main() { 
   int n1, n2;
   double result;
   cout << "Enter two number: ";
   cin >> n1 >> n2;
   try {
      cout << "The result is " << div(n1, n2) << endl;
   } catch (DivisionByZeroException &ex) {
      cerr << "Excetion: " << ex.what() << endl;
   }
   return 0;
}

异常旨在处理同步错误,例如数组的索引越界,除以零,算术溢出,无法分配内存等错误。异常处理机制无法处理异步错误,例如键盘和鼠标中断,网络消息接收,I / O操作等错误。这是因为这些事件是并行发生的,与程序控制流无关。

-重新抛出异常
程序可以决定部分处理异常或者根本不处理异常。在这种情况下,它可以将处理责任传递给其他处理程序。

void func1() {
   try {
      throw exception();
   } catch (exception &) {
      throw;
   }
}

int main() {
   try {
      func1();
   } 
   catch (exception &) {
   }
   return 0;
}

函数func1是在main程序的try块内调用的。函数func1还包含一个try … catch块。 throw语句抛出一个标准库中的异常类实例。catch处理程序(func1)捕获此异常并再次抛出它,然后由main中定义的catch块捕获。 main中的catch块对此异常并没有做任何处理,之后程序便结束了。

  • 异常说明

我们可以为一个函数指定一个可能抛出的异常列表。

void func1() throw(Exception1, Exception2,
      Exception3){
   // ...
}

此函数只能抛出throw列表中指定的异常。如果出现了不属于throw列表中指定的异常,则异常处理机制将调用意外处理函数并终止该程序的执行。然而,如果我们不提供throw列表,它会自动调用意外处理函数。(我们可以使用set_unexpected函数来自定义意外处理函数的具体行为。有关此内容的更多信息,请参阅C ++标准文档)。

void func1() throw(){
   // ...
}
  • 结论
    对于大多数现代编程语言来说,异常处理机制是其一项基本功能。有些语言(例如Java),从一开始就强调了这一点。因此,异常处理机制的使用是很普遍的。另一方面,C++语言是基于C语言发展的,异常处理机制是后来添加上的。此外,必须以这样的方式来利用异常处理能力,这样才能够不干扰已经存在的绝大多数代码,同时充分利用该机制的优点。因此,在将异常处理的设计决策纳入实际实现之前,需要考虑几个重要方面。 Andrew Koenig和Bjarne Stroustrup撰写的关于C ++异常处理的文章介绍了相关基本知识,并提供了一些关于异常处理机制的重要见解。

  • 参考文献
    Exception Handling for C++ by Andrew Koenig and Bjarne Stroustrup

  • 关于作者
    Manoj Debnath
    [email protected]

  • 相关文章
    Last.fm Open Sources C++ Moost Library Now Available
    CppDepend Pro License for C\C++ open source project contributors

栏目导航
上一篇:无
下一篇:技术文章翻译(二) – 一种简单的解决方案:使用Visual Studio Code编写C和C ++代码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章