C++异常(二)
c++ try–catch的语句原型如下:
try { //程序中抛出异常 throw value; } catch(valuetype v) { //例外处理程序段 }
在C++的异常中,程序接受到throw语句后就会自动调用析构器,把该域(try所在的大括号内)对象clean up,然后再进入catch语句(如果在循环体中就退出循环)。
这种机制会引起一些致命的错误,比如,当“类”有指针成员变量时(又是指针!),在 “类的构建器”中的throw语句引起的退出,会导致这个指针所指向的对象没有被析构。
比如:
class A{ public: A(){ t = new char[100]; //malloc in A() delete this; //delete object that has been defined,this program mean delete obj a throw 0; } ~A(){ delete[] t} }; //因为在构造函数中抛出异常,所以无法调用析构函数,t无法释放,new出来的100字节变成内存垃圾 int func(){ A a; A *p = new A(); delete p; return 0; }
所以我们可以通过把指针改为类就行了,比如模板类来代替指针,在模板类的内部设置一个析构函数。来解决问题。
如果抛出的是一个指针:
try{ throw new Y(); }catch(Y* p){ //whoops,forgot to delete.. //must delete p in this catch }
所以,更好的一种处理方式是,抛出的异常是堆栈里面的对象,catch的时候做一个引用。
struct A{ virtual void print(){...} }; struct B: public A{....}; try{ throw B("B error"); }catch(A& a){ a.print(); }
在C++中,如果有这样的函数:
void f(int x):throw(exception type1){ ... }
那么,在C++(在运行的时候处理异常)中,意味着在f()函数中,在运行的时候,f()函数最多只能抛出一个异常,而且是type1类型的。如果在函数f()中,抛出了别的异常,那么会有一个unexcepted异常抛出,去告诉函数f(),抛出了不是type1类型的异常。所以C++函数后面的throw是约束函数f()的:
void f():throw(){...} //函数f()不抛出任何异常,如果抛出,则unexcepted异常抛出 void f(){...} //函数f()可以抛出任何异常 void f():throw(T){...} //函数f()抛出T类型或T子类异常
而在Java中异常是在编译的时候处理的,如果是上面这样的函数,则是提示调用f()的时候,需要对type1的异常做出处理。也就是在try–catch中有针对type1的处理。(约束调用函数f()的调用者)
- void f():throw(){...} //函数f()抛出任何异常,如果抛出
- void f(){...} //函数f()不抛出任何异常
- void f():throw(T){...} //函数f()抛出T类型或T子类异常
上一篇: C++日常小题:射击游戏
下一篇: C语言实现简易通讯录