异常的抛出和处理主要使用了以下三个关键字: try、 throw 、 catch 。抛出异常即检测是否产生异常,在C++中,其采用throw语句来实现,如果检测到产生异常,则抛出异常。如果在try语句块的程序段中(包括在其中调用的函数)发现了异常,且抛弃了该异常,则这个异常就可以被try语句块后的某个catch语句所捕获并处理,捕获和处理的条件是被抛弃的异常的类型与catch语句的异常类型相匹配。由于C++使用数据类型来区分不同的异常,因此在判断异常时,throw语句中的表达式的值就没有实际意义,而表达式的类型就特别重要。所以catch块的参数可以没有参数名称,只需要参数类型。如果抛出的异常一直没有函数捕获(catch),则会一直上传到c++运行系统那里,导致整个程序的终止。
一般在异常抛出后资源可以正常被释放,但注意如果在类的构造函数中抛出异常,系统是不会调用它的析构函数的,处理方法是:如果在构造函数中要抛出异常,则在抛出前要记得删除申请的资源。catch块的参数推荐采用地址传递而不是值传递,不仅可以提高效率,还可以利用对象的多态性。另外,派生类的异常捕获要放到父类异常捕获的前面,否则,派生类的异常无法被扑获。编写异常说明时,要确保派生类成员函数的异常说明和基类成员函数的异常说明一致。
一个简单的例子:
#include <iostream> using namespace std; /* 如果在try{}程序块内发现异常,则由throw语句抛出异常,catch语句捕获异常 */ void main() { double a, b, c; cout << "输入a,b:"; cin >> a >> b; try { if (b == 0) throw c; //抛出异常 c = a / b; } catch (double) //捕获异常 { cout << endl << "除数不能为0!" << endl; exit(1); } cout << "a/b = " << c << endl; }
可以在函数的声明中列出这个函数可能抛出的所有异常类型:
void fun() throw(A,B,C,D);
此函数可以抛出任何类型的异常:
void fun();
不会抛出任何类型异常的函数可以进行如下形式的声明:
void fun() throw();
#include <iostream> #include <string> using namespace std; //自定义异常类 class DivideZero { public: DivideZero(string msg){ this->msg = msg; } void display(){ cout << msg << endl; } private: string msg; }; int test(int a, int b) { int c; if (b == 0) throw DivideZero("除数为0"); c = a / b; return c; } int main() { int c; try { c = test(3, 0); } catch (DivideZero e) { e.display(); } cout << c << endl; }