默认初始化抛出异常

Default initialization throws exception

本文关键字:抛出异常 初始化 默认      更新时间:2023-10-16

假设我们有一个类(称为classs),它的默认构造函数可能抛出一些异常。我需要在函数中使用该类的对象,如下所示:

try{
   classs c;
} catch(bad_init& b){
    //log
}
//if the class initialized succesfully
//do some with c

但是c是在try的块作用域中声明的,因此在函数作用域中不可见。我该怎么做呢?

我不想包装整个函数体,因为有些代码会抛出另一种异常。

您不能直接这样做。只要c在作用域中,代码就有权假定它包含classs类型的活动对象。如果构造函数抛出异常,c将不会初始化,并且不能保持。

正确的方法是将c的整个作用域包装在try块中。毕竟,如果c初始化失败,使用c的代码就不能做任何有意义的事情。如果该块后面的其他代码可能会抛出其他异常,而您不想捕获它们,那么就不要让它们在堆栈中正常传播。

如果由于某种原因不能使用这种方法,您可以求助于boost::optional和延迟init:

boost::optional<classs> c;
try {
  c = classs();
} catch (bad_init&) {
}

或者手动执行std::aligned_storage,放置new和条件析构函数调用的类似操作。

变通方法是使用std::unique_ptr:

std::unique_ptr<A> a;
try{
   a = std::make_unique<A>();
} catch(bad_init& b){
    //log
}
if (a){
 //do 
}

我将简单地在调用者级别捕获异常。没必要把事情弄复杂。

void functionThatThrows()
{
    classs c;
    // do something with c
}
void callerThatCatches()
{
    try {
        functionThatThrows();
    } catch(...) {
        // handle exception
    }
}

最简单的方法就是扩展try块,直到你不再需要你的对象:

try{
    classs c;
    //if the class initialized succesfully
    //do some with c
} catch(bad_init& b){
     //log
}