关于异常处理的一些问题

Some Question regarding Exception handling

本文关键字:问题 异常处理      更新时间:2023-10-16

请看一下演示代码:

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的处理程序才重新抛出异常

当您简单地在ctor内部抛出异常时,它的处理程序不会重新抛出对象?即

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

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

通常的规则是catch块不会重新抛出,除非你问它到。否则,您将如何阻止异常传播。在里面然而,构造函数的情况是,如果初始化中有什么东西list抛出,那么您还没有得到一个完全构造的对象;有你不能对对象做任何事情,甚至不能调用上的析构函数如果构造函数的函数catch块没有重新思考,它将做什么,因为它不能简单地返回(以及将变量留在堆栈上)?

在所有其他情况下,包含catch块的函数由用户决定知道该做什么。例如,在你的主菜的情况下,你可以写入:尝试{ab-bb;}捕获(…){}std::cout<lt;"已恢复执行!"<lt;std::endl;

您不能执行bb在作用域和可访问,但尚未正确构建。

至于为什么不应该在基础课,我从来没听说过这个规则。通常,析构函数不应该扔,所以把它们包在试块里没有意义,时期

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

和往常一样,Herb Sutter知道并解释了一切:

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

更多信息,请参阅他的文章