繁体   English   中英

堆栈对象的C ++构造函数异常处理

[英]C++ constructor exception handling for stack object

给定一种情况,我想让一个堆栈分配的对象可能在构造过程中抛出,但又想在调用站点处处理异常,如何使该对象从构造它的try块外部可以访问?

例如

class MyThrowingClass {

MyThrowingClass() {throw exception();}

doSomethingImportant() {
//...
}

};

int main() {

//Need to catch the exception:
try {
MyThrowingClass myObj;
} catch() {
//actually handle the error
//...
}

//Also need to use myObj later on
myObj.doSomethingImportant();//but we can't use it here because it was scoped to the try block...
}

如果我将myObj放入try中,则try范围之外的任何内容都看不到,但是我不想在其中包含其他所有内容,因为这样代码就会变成30个嵌套的try块级别,这就是异常处理的内容应该使用替代初始化函数错误代码删除。

我无法在构造函数中处理异常,因为对异常的反应取决于M​​yThrowingClass的使用上下文。

显然,可以通过以下方法解决该问题:

MyThrowingClass* pMyObj;

然后能够包装

pMyObj = new MyThrowingClass();

但是肯定也可以使用堆栈分配的对象来实现吗?

是做类似事情的唯一解决方案

MyThrowingClass myObj;

try {
    myObj.init();
} catch(...) {
//...
}

在这一点上,我们又回到了与错误代码一样糟糕的程度,并且拥有未初始化或部分初始化的对象。

请注意,这并不是要成为全局对象,我想在许多地方都可以实例化某些东西。

确实有一个try块是一个理想的解决方案,它包装了整个作用域(这里将包含在main内的所有内容),并在那个try块的末尾捕获了处理所有可能异常的捕获,而不是能够模糊地处理异常到他们的网站?

int main() {
try {

//absoultely everything

}
catch (exceptionTypeA &a) {
//...
}
catch exceptionTypeB &b) {

}

}

如何使对象从构造它的try块外部可以访问?

如果构建失败,则该对象不存在;否则,该对象将不存在。 所以没有东西可访问。

当然这也应该可以通过堆栈分配的对象来实现吗?

自动(即堆栈分配)对象仅初始化一次,因此即使您处理了异常,也无法返回并尝试重新初始化它。 如果确实希望重试,则必须使用更复杂的方法,例如建议的动态分配或两阶段初始化。 另一种选择是boost::optional (或者从明年开始, std::optional ),它使您可以在一次自动存储中std::optional创建和销毁对象。

拥有包裹整个作用域的try块真的是理想的解决方案吗?

在典型情况下,不是在本地处理异常,并且初始化失败表示发生了不可恢复的错误,是的。 在特殊情况下,您可以在本地处理它并进行恢复,没有。

try被设计为作用域可以由于某种原因抛出的对象。 通过解决它,您正在避开它试图保护您的内容(使用定义不明确的对象)。考虑使用函数来生成对象。 通过使用noexcept move构造函数,可以保证移出对象是安全的:

class MyThrowingClass {
  public:
    MyThrowingClass() {
        throw exception();
    }

    // throw() is *okay* if you don't have noexcept
    MyThrowingClass(const MyThrowingClass && other) noexcept { 
    }

};


MyThrowingClass GetObj() {
    try {
        return std::move(MyThrowingClass());
    } catch(...) {
        // return some well defined default or terminate program
    }
}

int main() {
    MyThrowingClass myObj(std::move(GetObj()));
}

给定一种情况,我想让一个堆栈分配的对象可能在构造过程中抛出,但又想在调用站点处处理异常,如何使该对象从构造它的try块外部可以访问?

基本上,你不能。 至于将所有代码包装在try块中是个好主意,这取决于“所有代码”的大小-十几行左右没什么大不了的。

如果初始化程序抛出异常,您真的要调用MyThrowingClass::doSomethingImportant()吗? 除非您以某种方式保证在catch修复损坏的初始化,否则您将在部分初始化的对象上调用方法。

在与对象的构造相同的try块中包含对doSomethingImportant()的调用将为您提供确切的异常设计:在出现问题时,跳过以下代码(取决于前面的代码)以错误处理程序。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM