假设我们有一个可能会抛出异常的构造函数。
class A{
public:
A(); // may throw exceptions
};
我们可以使用这种方式来捕获异常:
try{
A a;
// do somethings to a, and I have to put everything about a here
}catch(...){
// handle exceptions
}
所以我的问题是如何避免在不使用指针的情况下将所有内容都放在 try-catch
block 中。
最佳答案
您可以定义一个创建函数来为您处理异常,并在发生异常时返回一个合理的默认值,例如:
struct A
{
A() : data("Default")
{
std::cout << "In A()" << std::endl;
}
A(const A& other) : data(other.data)
{
std::cout << "In A(A)" << std::endl;
}
A(bool param)
{
std::cout << "In A(bool)" << std::endl;
if(param)
throw std::runtime_error("Failed");
data = "Hello";
}
std::string data;
};
A createA(bool param, A& def_a)
try
{
return A(param);
}
catch (...) {
//...
return def_a;
}
然后您可以使用此函数的返回值启动您的实际 A
。由于 RVO,如果创建成功则不会执行任何复制,只有在创建失败时才会执行(因为它必须随后复制默认值):
int main(int argc, char**args)
{
A defA;
A a1 = createA(true, defA);
A a2 = createA(false, defA);
std::cout << "A1: " << a1.data << std::endl;
std::cout << "A2: " << a2.data << std::endl;
return 0;
}
这个的输出是:
In A()
In A(bool)
In A(A)
In A(bool)
A1: Default
A2: Hello
第一个构造函数是默认值。然后您可以看到在第一个 A(bool)
调用(抛出)之后,进行了复制构造函数调用以返回默认值。第二次调用没有失败,没有复制构造函数调用(由于 RVO)。在此之后,您将得到一个默认的 A
和一个成功创建的 A
,您可以在之后使用它。
当然,如果复制构造函数也可以抛出异常,那么您可能会遇到异常转义 createA
- 如果是这种情况,您将不得不稍微修改此设计。
关于c++ - 如何从 C++ 中的构造函数中捕获异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38395879/