c++语句补充

来源:互联网 发布:gbase数据库 编辑:程序博客网 时间:2024/06/06 09:21

try块和异常处理(关于c语句的补充)

   在设计各种软件的系统中,异常是程序错误处理的一部分。当程序代码检查到无法处理的问题时,异常处理就特别有用。在这些情况下,检测出问题的那部分程序需要一种方法把控制权转到可以处理这个问题的那部分程序。错误检测程序还必须指出具体出现了什么问题,并且可能需要提供一些附加信息。
异常机制提供程序中错误检测与错误处理部分之间的通信。C++的异常处理中包括:

  1. throw表达式,错误检测部分使用这种表达式来说明遇到了不可处理的错误。可以说,throw引发了异常条件。
  2. try块,错误处理部分使用它来处理异常。try语句块以try关键字开始,并以一个或多个catch子句结束。在try块中执行的代码所抛出(throw)的异常,通常会被其中一个catch子句处理。由于它们“处理”异常,catch子句也称为处理代码。
  3. 由标准库定义的一组异常类,用来在throw和相应的catch之间传递有关的错误信息。

1. throw表达式

系统通过throw表达式抛出异常,throw表达式的类型决定了所抛出异常的类型。

/*两个Sales_item类型对象相加的程序,检查读入的记录是否来自同一本书。如果不是就输出一条信息然后退出程序*/Sales_item item1, item2;//首先检查item1和item2是否是同一本书if(item1.same_item(item2)){  std::cout << item1 + item2 << std::endl;  retuen 0;}else{  std::cout << "data must refer to same ISBN" << std::endl;  return -1;}

2.1 try块

try块的通用语法形式是:
try {
program-statements
} catch (exception-specifier) {
handler-statements
} catch (exception-specifier) {
handler-statements
}//…
try块以关键字try开始,后面是用花括号括起来的语句序列块。try后面是一个或多个catch子句。每个catch子句包括三个部分:关键字catch、异常说明符( exception-specifier )以及语句块{ handler-statements }。一旦catch子句执行结束,程序流程立即继续执行紧随最后一个catch子句后的语句。
在try块中声明的变量,包括catch子句中声明的变量,不能在try外面使用。

Sales_item item1,item2;  while (cin >> item1 >> item2)  {      try      {          if (!item1.same_isbn(item2))          {              throw runtime_error("Data must refer to same ISBN");          }      }      catch (runtime_error err)      {          cout << err.what()               << "\nTry Again? Enter y or n" << endl;          char c;          cin >> c;          if (cin && c == 'n')          {              break;          }      }      cout << item1 + item2 << endl;  }  

在执行try块代码的过程中,如果在try块中的代码抛出runtime_error类型的异常,则处理这类异常的动作在catch后面的块语句中定义。

2.2 函数在寻找处理代码的过程中退出

   寻找处理代码的过程与函数调用链刚好相反。抛出一个异常时,首先要搜索的是抛出异常的函数。如果没有找到匹配的catch,则终止这个函数的执行,并在调用这个函数的函数中寻找相配的catch。如果仍然没有找到相应的处理代码,该函数同样要终止,搜索调用它的函数。如此类推,继续按执行路径回退,直到找到适当类型的catch为止。
   如果不存在处理该异常的catch子句,程序的运行就要跳转到名为terminate的标准库函数,该函数在exception头文件中定义。这个标准库函数的行为依赖于系统,通常情况下,它的执行将导致程序非正常退出。
   在程序中出现的异常,如果没有经try块定义,则都以相同的方式来处理:毕竟,如果没有任何try块,也就没有捕获异常的处理代码(catch子句)。此时,如果发生了异常,系统将自动调用terminate终止程序的执行。

/*bitset类提供to_long操作,如果bitset提供的位数大于unsigned long 的长度时,抛出一个overflow_error异常,捕获这种异常并输出提示信息*/#include<iostream>#include<bitset>using namespace std;int main(){    bitset<100> bit = 0x7fffffff;    unsigned long int ans;    try    {        if(bit.size() > sizeof(ans)*8)            throw overflow_error("the bit is too long.");    }    catch(overflow_error err)    {        cout << err.what()             << "\ntry again? enter y or n " << endl;        char c;        cin >> c;        if(cin && c == 'n')            return -1;    }    return 0;}

3. 异常标准

C++定义了一组类,用于报告在标准库中的函数遇到的问题。标准库异常类分布在四个头文件中:
1)exception头文件:定义了最常见的异常类,类名为exception,该类只通知异常的产生,不会提供更多的信息。
2)stdexcept头文件:定义了几种常见的异常类,见下表:
image
3)new头文件:定义了bad_alloc异常类型,提供了因为无法分配内存而由new抛出的异常。
4)type_info头文件:定义了bad_cast异常类型。

   异常类型只定义了一个名为what的操作。这个函数不需要任何参数,并且返回const char* 类型值。它返回的指针指向一个C风格字符串。使用C风格字符串的目的是为所抛出的异常提出更详细的文字描述。
   what函数所返回的指针指向C风格字符数组的内容,这个数组的内容依赖于异常对象的类型。对于接受string初始化式的异常类型,what函数将返回该string作为C风格字符数组。对于其他异常类型,返回的值则根据编译器的变化而不同。

4. 使用预处理进行调试

程序所包含的调试代码仅在开发过程中执行,当应用程序已经完成,并且准备提交时,就会将调试代码关闭。可以使用NDEBUG预处理变量实现有条件的调试代码:

int main(){#ifndef NDEBUGcerr << "starting main" << endl;#endif//...}

默认情况下,NDEBUG未定义,这也就意味着必须执行#ifndef和#endif之间的代码。在开发程序的过程中,只要保持NDEBUG未定义就会执行其中的调试语句。开发完成后,可通过定义NDEBUG预处理变量,(有效地)删除这些调试语句。