如何从C++中的构造函数中捕获异常
How to catch exceptions from a constructors in C++
假设我们有一个可能会抛出异常的构造函数。
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
块中。
您可以定义一个为您处理异常的创建函数,并在发生异常时返回合理的默认值,例如:
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
- 如果是这种情况,你将不得不稍微修改这个设计。
一种可能的方法是使用哨兵。
class sentry {
public:
bool exception_thrown=true;
void constructed()
{
exception_thrown=false;
}
~sentry()
{
if (exception_thrown)
{
// Whatever you want to do
}
}
};
然后:
sentry a_sentry;
A a;
a_sentry.constructed();
在哨兵的析构函数中,如果设置了exception_thrown
,那只能是因为在A
的构造函数中抛出了异常,因为该标志在完全构造后立即被清除A
。因此,将清理代码放在析构函数中。使用此方法时必须小心的一件事是析构函数本身不能引发自己的异常。
然后,您还可以执行以下操作:
class A_with_sentry : public sentry, public A {
public:
A_with_sentry()
{
constructed();
}
};
然后只需声明:
A_with_sentry a;
然后,更进一步,使其成为模板函数,让构造函数将其可变参数完美地转发给 sentry 对象的构造函数,等等......
还有其他方法,但不建议这样做,因为您需要处理指针。
A* a=nullptr;
try {
a = new A();
}
catch(...){
}
if(a){
//do somethings to a, and I have to put everything about a here
delete a;
}
相关文章:
- 从构造函数抛出异常时如何克服内存泄漏
- 如何编写带有异常的构造函数
- 如何捕获源自静态分配对象的构造函数的异常?
- C++:如何捕获构造函数引发的异常?
- 班级成员在C Lambdas中捕获内部构造函数
- 异常构造函数中的例外
- 分配内存后,构造函数处出现未捕获的异常
- 捕获构造函数抛出的异常似乎是不可能的
- C++11 引入了采用 'const char*' 的异常构造函数.但是为什么
- 如果文件在构造函数中不存在,则抛出异常,并在 main() 中创建对象时尝试/捕获它,如果好 - 开始使用该对象
- 我应该在哪里捕获构造函数中抛出的C++异常
- 尝试/捕获类构造函数C++"中间"
- C++在构造函数中捕获异常
- 在异常构造函数中参数化错误消息是一种好的做法吗
- 从构造函数捕获异常意味着我的实例之后超出了作用域
- 异常构造函数来填充字符串流
- 如何从构造函数中成员的默认初始化中捕获异常
- 如何捕获构造函数异常
- 捕获构造函数异常的RAII方法
- 如何从C++中的构造函数中捕获异常