请查看演示代码:
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();
}
我的问题:
当你只是在ctor中抛出异常时,它的处理程序不会重新抛出对象?即
Ctor::Ctor()
{
try{
throw Excep1();
}
catch(Excep1& temp) {
std::cout<<"Doesn't rethrows the exception object";
}
}
我想知道如何在处理重新生成的对象后将控制权恢复为cout << "Resumed execution!" << endl;
?
为什么经常说我们不应该在基类的dtor上放置函数try块?
答案 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块的末尾,那么原始异常会自动重新抛出。