关于异常处理的一些问题

时间:2011-06-29 15:34:57

标签: c++ exception-handling

请查看演示代码:

class myError
{
    const char* str;
public:
    myError():str(NULL) {}
    myError(const char* temp)
    {
        str = temp;
    }
    const char* what()
    {
        return str;
    }
};

class ab
{
    int x;
public:
    ab() try :x(0)
    {

            throw myError("error occured in the constructor of class ab");
    }
    catch(myError& temp)
    {
        std::cout<<"Handler no. 1 of ab constructor"<<std::endl;
    }
};

int main () try
{
    ab bb;
    cout << "Resumed execution!" << endl;
    return 0;
}
catch(myError& temp)
{
    std::cout<<"Handler below the main function"<<std::endl;
    std::cout<<"And the error is :" <<temp.what();
}

我的问题:

  1. 为什么只有函数try块的ctor处理程序和dtor只重新发现异常? ,
  2. 当你只是在ctor中抛出异常时,它的处理程序不会重新抛出对象?即

    Ctor::Ctor()
    {
        try{
            throw Excep1();
        }
        catch(Excep1& temp) { 
            std::cout<<"Doesn't rethrows the exception object";
        }
    }
    
    1. 我想知道如何在处理重新生成的对象后将控制权恢复为cout << "Resumed execution!" << endl;

    2. 为什么经常说我们不应该在基类的dtor上放置函数try块?

3 个答案:

答案 0 :(得分:7)

通常的规则是catch块不会重新抛出,除非您提出要求 至。如何阻止异常传播。在 但是,如果是初始化中的某些东西,则是构造函数的情况 列表抛出,然后你没有一个完全构造的对象;有 你无法用对象做任何事情,甚至没有打电话给析构函数 它。如果构造函数的函数catch块没有 重新抛出,它将要做什么,因为它不能简单地返回(和 把变量留在堆栈上??

在所有其他情况下,它包含catch块的功能 知道该怎么做。例如,在您的主要情况下,您可以 写:     尝试{         ab bb;     } catch(...){     }     std :: cout&lt;&lt; “恢复执行!” &LT;&LT;的std :: ENDL;

你不能做的是执行bb范围内的代码 可以访问,但没有正确构建。

至于为什么你不应该在一个函数的析构函数上放置一个函数try块 基类,我从来没有听说过这个规则。一般来说,析构函数 不应该抛出,所以将它们包装在try块中是没有意义的, 周期。

答案 1 :(得分:1)

对于第二个问题,析构函数不应该是投掷期。考虑一下析构函数通过delete释放大量内存的情况。如果您的析构函数在完成清理之前抛出错误会发生什么?你现在有内存泄漏。如果析构函数导致运行时错误,那么您可能在代码中的其他位置遇到需要修复的问题。

答案 2 :(得分:0)

通常,Herb Sutter知道并解释一切:

  

如果处理程序主体包含语句“throw;”那么catch块显然会重新抛出A :: A()或B :: B()发出的异常。不太明显,但在标准中明确说明,如果catch块没有抛出(重新抛出原始异常,或抛出新的东西),并且控制到达构造函数或析构函数的catch块的末尾,那么原始异常会自动重新抛出。

More in his article