异常处理
异常处理思想:
许多异常是可以预料的,但无法避免,如:用户输入错误、内存溢出、打印机未连接好,文件不存在、无U盘等。
处理方法:最好能暂停当前工作,允许用户排除错误继续执行程序,或至少给出适当的提示信息。
异常:发现、抛出、检测、捕获和处理异常。
throw(抛出异常)
可以抛出一个任何类型的异常,可以是基本数据类型,也可以是自定义类型,异常类(自定义异常类用于保存异常发生时的信息,用于给出提示,处理异常)。
标准异常类:
-
头文件< stdexcept>
-
exception标准异常类
C++标准库异常类继承层次中的基类为exception,
-
除了exception类,C++还提供了一些派生类,用于报告程序不正常的情况,在这些预定义的类中反映的错误模型中,主要包含逻辑错误(logic_error)和运行时错误(runtime_error)两大类。
-
what(const char * s)函数
参数为字符串类型,用于描述异常。
- C++在异常抛出前会自动为所有异常发生之前构造的局部对象调用析构函数
try(检测异常)
-
在try块中抛出异常才能被检测,从而进一步捕获处理。
-
try检测到异常后,会跳过下面的语句,跳转到对应的catch语句。
-
如果当前函数没有用try块(和catch)捕获异常或catch没有捕获到该异常,则系统继续将该异常抛给调用它的函数!直到遇到一个能捕获此异常的函数或OS。即没有处理异常的函数遇到异常相当于执行了再次抛出功能(执行throw语句)
catch(捕获、处理异常)
-
一个类可以抛出多个异常,一个try块也可以对应多个catch语句,但最多只执行一个catch语句(不需要break)。顺序检测到匹配的第1个catch语句并执行,然后自动跳过后面的所有catch语句。
-
catch(…) 可以接收所有类型的异常
-
当catch块捕获的异常类型与try块中抛出的异常类型不同时,该catch块将不会被执行,因此也就不会捕获到异常!
-
有时处理程序在捕获到一个异常对象之后,仍不知道如何处理,为此它要把这个异常对象再次抛出,希望其他函数能更好地处理它。
-
基类的catch语句也将匹配从该基类派生的任何类。
因此,如果想捕获基类类型和派生类类型的异常,则应在catch序列中将派生类置于前面,否则将永远执行不到,编译器会给出警告。
异常接口
可以在函数定义中限定函数能够抛出的异常种类。
缺省允许抛出任何类型的异常,throw()子句限制函数不能抛出异常。
/*************************************************
int func() throw();不允许该函数抛出异常
int func();该函数可以抛出任何异常(缺省值)
int func() throw(Cx,Cy);限制该函数只能抛出Cx和Cy
两种类型的异常
**************************************************/
// Restricting function throw types.
#include <iostream>
using namespace std;
// This function can only throw ints, chars, and doubles.
void Xhandler(int test) throw(int,char,double)
//改为:void Xhandler(int test) throw(char,double)导致运行时错误!
{
if(test==0) throw test; // throw int
if(test==1) throw 'a'; // throw char
if(test==2) throw 123.23; // throw double
}
int main()
{
cout << "Start\n";
try{
Xhandler(0); // also, try passing 1 and 2 to Xhandler()
}
catch(int) {
cout << "Caught int\n";
}
catch(char) {
cout << "Caught char\n";
}
catch(double) {
cout << "Caught double\n";
}
cout << "End\n";
return 0;
}
异常嵌套
异常可以嵌套,也就是在catch语句处理异常时,catch语句本身也可以捕捉异常并做相应处理。
不过由于这种嵌套形式过于复杂,难于理解,因而并不建议使用。