C++ 异常处理
在程序运行过程中,报错这个东西是在异常出现后用于防止继续程序的动作。这些异常,包括用户的,逻辑的,系统的都可以使用一个函数来识别。如果识别的程序不能够处理异常,那么就会抛出一个异常。而能够处理该异常函数就会接收并进行处理。
在C++中,当一个异常被抛出,它就必须被处理,否则会导致一些程序的报错或终止。如果用户异常处理不存在,编译器就会提供一个默认机制来终止程序
异常处理比常规的程序流程控制(如循环语句或 if 语句)更占用资源。常规情况下最好不要使用异常机制,将它留在真正“不寻常”的情形下使用吧。
当不能在局部范围内处理时,异常非常有用的。您可以直接将流程控制转移到可以处理错误的地方,以此取代在程序中抛出出错状态。
例如,一个方法可能具有打开文件和初始化一些相关数据的任务。如果这个文件无法打开或者已经损坏,这个方法将无法执行这个任务,无论如何,这个方法可能没有处理好这个问题。此方法会抛出一个异常对象描述出错原因,当前程序将中断运行在此异常的上一个位置。这个异常处理可能会自动尝试备份文件,并询问用户是否尝试打开另一个文件,或完全关闭当前占用文件的程序,除了异常处理,状态和数据会接着传递下去并且返回到此方法的调用位置,每个方法调用后附带状态检查。带有异常处理,程序的支配运行才不会被错误检查所覆盖。如果一个方法执行完返回,此方法的调用代码一定会成功执行。
异常处理也有缺点。如果一个方法因为它本身或它调用的方法抛出异常而没有正常返回的话, 那数据的一致性可能遭到破坏。你需要知道异常什么时候可能会被抛出,以及该异常是否会对你的程序造成不良影响。
异常处理是每个c++程序不可缺少的部分. 没有它,写程序会变的很困难而且很耗时间. 下面的这些例子会帮助你更加简单和快速的编程。
这篇文章主要关注异常处理中的三个保留字:try、throw和catch。通常try块尝试执行一段代码,如果因为任何原因失败,该代码段会抛出错误,这些错误可以被catch块捕获并且执行一段可选的代码。
只有在try块中的代码才会用于异常监测。如果异常无法抛出,那么会引起程序调用exit()或者abort()函数异常退出,比如double类型变量并不兼容int异常,如下代码所示:
Listing 1:在try块内的代码将会被监测
1 Try { 2 throw 100; //Throw an error. 3 } 4 catch (double i) { // Catch will not execute and program will terminate 5 cout << "Exception caugh: " << i << ".\n"; 6 getch(); 7 }
异常002
现在我们来看一下程序是如何运行的。try block(C++的一个东东)包含许多的处理,这些处理有些会得到执行而有些不会执行,在它未运行前,所有的情况就已经确定了。但这取决与用户的输入,不同的输入会导致程序往不同的方向执行。如果throw被执行了,那么用户或者系统可能做了一些不允许做的事。
下面请注意以下代码在else内throw下的执行内容。该代码并不会被执行,事实上,程序甚至不会注意到他。在throw调用后的代码正如goto代码后的执行语句一样都是不可能执行到的(某些特定情况可以排除哈,如果是goto下一行呢,呵呵)
例子2:Else情况下的执行代码
1 try 2 { 3 system("cls"); 4 cout << "What is the name: "; 5 cin >> gotostr; 6 if(gotostr == "Scooter" || gotostr == "scooter" || gotostr == "SCOOTER") 7 { 8 cout << "That is the right name.\n"; 9 getch(); 10 system("cls"); 11 return 0; 12 } 13 else 14 { 15 throw gotostr; 16 cout << "This code is useless.\n"; 17 } 18 }
最后,catch是这三部分处理的最后一部分。它捕获抛出的变量也只能捕获该变量。接着他就会执行相应变量捕获后的处理代码。捕获可以捕获任何你定义好了的变量,正如下面一样。如果你抛出string,那么你就需要把捕获的参数定义为string,如果你捕获int值,你就应该把捕获的参数定义为int值
例子3:设计捕获代码
1 catch (string gotostr) 2 { 3 system("cls"); 4 cout << "Error, Press any key to try again.\n"; 5 getch(); 6 goto begin; 7 }
如果大家真的喜欢c++的话,可以看how to program ++ 和 C++ primer,这是c++作者的两本书,比这里写的清楚一万倍,而且国内有翻译版了,不过读懂英文原版会更好,翻译总是带点作者的个人色彩.
最终这些都是工具,就好比你懂得了英文没有,你要用他来写文章,其实程序也一样的
Exception 003
上面的那些例子是为了说明try-catch的工作原理。但是,在实际的c++编程中,这并不总是有用。然而,以下例子将显示在程序中操作异常是可能的。现实中许多程序包括异常类类型。因此,仿照以下例子,你首先要做的就是写一个类。
列表4:高级异常操作
1 class interror 2 { 3 public: 4 char str_error[80]; 5 int why1; 6 7 interror() 8 { 9 *str_error = 0; why1 = 0; 10 } 11 12 interror(char *e, int w) 13 { 14 strcpy(str_error, e); 15 why1 = w; 16 } 17 };
这是一个相当简单的类,包括两个变量(str_error和why1)。这些变量需要更加简单地操作来自同一个问题的各种异常。我们用这个变量并且只写一次异常,而不是一遍又一遍重复地写。
现在写入主程序部分。
列表 5: 使用str_error和why1变量
1 int main() 2 { 3 int i; 4 int n; 5 try 6 { 7 cout << "Enter a denominator: "; // When you run this program enter 0. 8 cin >> n; 9 if (n == 0) 10 { 11 throw interror("Cannot divide by: ", n); 12 } 13 else 14 { 15 i=100/n; 16 cout << "The answer is " << i << "\n"; 17 } 18 } 19 catch (interror e) 20 { 21 cout << e.str_error << ": "; 22 cout << e.why1 << "\n"; 23 } 24 return 0; 25 }
这段程序是以变量i和n的声明开始的,这两个变量是后面程序表达式的基础。接下来,程序要求输入一个数字,作为除法的分母。再次之后,异常处理机制就开始生效。
在if语句之后,就是我们所介绍过的抛出这个类的异常。
1 throw interror("Cannot divide by: ", n);
throw 段会抛出我们自定义的class interror类型异常,并告诉程序抛出的是什么异常(即打印出的错误消息)当程序抛出类异常并且被捕获之后它将打印出str_error,显示异常消息,而变量why1则表面程序不接受什么样的数字,在该例子中是0。
该程序的输出是:
Enter a denominator: 0
Cannot divide by: 0
Press any key to continue.
总结
这篇文章让我们了解到了在C++中关于异常处理的技术,但是这仅仅是开始,在你以后的C++的旅程中你将会学习到更多关于异常处理的有趣且功能强大的技术。