int amount;
try {
cin >> amount;
if(amount < 0)
throw amount;
}
catch(int e) {
cout << amount << " is negative\n";
}
C++中,基本的异常处理是try-throw-catch。try block中包含想要尝试执行的语句。上例中throw amount;中的amount有时被叫做exception,throw语句叫做throw an exception,可以throw任意类型的值。当throw语句被执行时,try block中的执行被中断,程序的控制被转交给catch block,这个过程被叫做catch/handle the exception,catch block也通常被叫做exception handler。catch(int e)中的 e 被叫做catch-block parameter
如果throw语句没有被执行,在try block的最后一条语句被执行完后,会执行catch block后面的第一条语句,catch block会被忽略。如果一个exception被抛出但没有被catch,则程序会被终止,但这是合法的。如果在try block中嵌套使用try-catch并且在内层try中抛出的exception未被catch,则它会被抛出到外层try block处理并可能在那里被catch
C++中有一个预定义的函数叫做"terminate",它会在一个exception被抛出但未被catch时被调用。terminate函数会调用另一个名为"abort"的函数,abort函数会终止程序。terminate可以被redefine,进而在退出程序前调用另一个函数而不是abort,只要用"set_terminate"函数,将希望被调用的函数名作为参数传递给set_terminate即可
void end_func(void);
try {
set_terminate(end_func); // call end_func when an exception is not caught
...
throw("this is exception won't be caught")
}
catch(int) {
...
}
throw语句可以抛出任意类型的值,通常的做法是定义一个class。try block可以throw多种类型的变量,但是在一次执行中只能抛出一个exception。一个catch block只能catch一种类型的exception,但是可以定义多个catch block来处理不同类型的exception。下例中,catch block没有parameter,如果catch block不需要parameter,只要列出类型即可。同时,"..."并不是省略,而是就可以使用三个点来表示default catch block,由于catch block的检查是顺序执行的,因此catch(...)要放在最后
class DivideByZero {};
...
try {
if(divisor == 0)
throw DivideByZero();
}
catch(DivideByZero) {
cout << "Divisor is 0\n";
}
catch(...) {
cout << "Unexplained exception\n";
}
lass DivideByZero {};
void safe_divide(int dividend, int divisor) throw (DivideByZero, OtherExceptions); // declaration
...
void safe_divide(int dividend, int divisor) throw (DivideByZero, OtherExceptions) {
if(divisor == 0)
throw DivideByZero();
...
}
void function() throw (DivideByZero, AnotherException); // only exception "DivideByZero" and "AnotherException" are treated normally, any other exception will end the program if not caught in function body
void function() throw (); // empty exception list, all exceptions will end the program if thrown but not caught in function body
void function(); // all exceptions are treated normally
如果没有exception specification(没有throw list,连空也没有),则就相当于所有可能的exception类型都在exception specification中被列出了;而如果一个exception被抛出但却没有被列在exception specification中并且也没有在函数外被catch,则程序会终止。
由于一个derived class的object同时也是它base class的object,所以如果class D是class B的derived class并且B在exception specification中,那么被抛出的D类object也会被正常处理。当在derived class中redefine或override一个函数时,它只能有与base class中相同的exception specification,或是base class中该函数exception specification的子集。也就是说,redefine或override一个函数时,只能删除某些exception,而不能添加新的exception
class MyException {};
void f1() throw (MyException) {
...
throw MyException();
...
}
void f2() {
...
try {
...
f1();
...
}
catch(MyException e) {
...
}
...
}
在现实中,最好的方法是将exception的throw和catch分别写到两个不同的函数中。并且,即使是这种方法最好只在不可避免的情况下抛出exception。如果能够简单地用其他方法解决问题,就不要使用exception。只在
当exception的处理方式取决于函数被调用的位置和方式
时使用exception,对于其他的情况,最好不要抛出exception