欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

C++异常(二)

程序员文章站 2022-07-28 21:12:50
c++ try–catch的语句原型如下: try { //程序中抛出异常 throw value; } catch(valuetype v) {...

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子类异常