Exception Handling

Posted xero10

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Exception Handling相关的知识,希望对你有一定的参考价值。

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


有时可以延迟异常处理。例如,可以在一个函数定义中抛出一个exception但并不catch,然后在调用该函数的程序处再catch(此时函数要在程序的try block中被调用)。如果有exception在函数定义中被throw但没定义catch,那么这些exception类型要被列在exception specification中。如果一个函数有多次声明,则exception specification必须出现在每一次声明中,并且必须相同。一个函数的exception specification也被叫做throw list。如果有多个类型的exception,用","进行分隔。要记住exception specification是针对在函数外被处理的exception的,如果一个exception在函数中已经有对应的catch了,则它就不应该出现在exception specification中。如果一个函数定义包含了另一个可能会抛出exception但没有被catch的函数,则这个exception类型也要被包含在exception specification中

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

以上是关于Exception Handling的主要内容,如果未能解决你的问题,请参考以下文章

Exception handling

ruby exception_handling.rb

/EH (Exception Handling Model)

python handling-exception-example.py

Exception Handling

Java 异常处理 (Exception Handling)