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
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