从构造函数捕获异常意味着我的实例之后超出了作用域
Catching exceptions from a constructor means that my instance is out of scope afterward
我有一个类,它的构造函数可能抛出异常。下面是一些捕获异常的代码:
try {
MyClass instance(3, 4, 5);
}
catch (MyClassException& ex) {
cerr << "There was an error creating the MyClass." << endl;
return 1;
}
但是当然,try/catch之后的代码不能看到instance
,因为它现在超出了作用域。解决这个问题的一种方法是分别声明和定义instance
:
MyClass instance;
try {
MyClass instance(3, 4, 5);
}
...
只是我的类没有合适的零参数构造函数。事实上,这里的这种情况是唯一一个这样的构造函数有意义的情况:MyClass
对象是不可变的,也就是说它的数据成员在构造之后都不会改变。如果我要添加一个零参数构造函数,我需要引入一些实例变量,比如is_initialized_
,然后在继续之前检查每个方法以确保该变量是true
。对于这样一个简单的模式来说,这似乎太冗长了。
处理这种事情的习惯方法是什么?我需要忍受它并允许我的类的实例在初始化之前被声明吗?
你应该在 try
块内做你需要做的一切:
try {
MyClass instance(3, 4, 5);
// Use instance here
}
catch (MyClassException& ex) {
cerr << "There was an error creating the MyClass." << endl;
return 1;
}
毕竟,只有在try
块内,instance
才被成功地创建,从而可以使用。
我想知道你的catch
块是否真的在处理异常。如果你不能做任何事情来解决这种情况,你应该让它传播。
使用new
:
std::unique_ptr<MyClass> instance;
try
{
instance.reset(new MyClass(3, 4, 5));
}
catch (const MyClassException& ex)
{
std::cerr << "There was an error creating the MyClass." << std::endl;
return 1;
}
// use instance as needed...
您可以使用一个通用的帮助函数来捕获异常和未来的std::optional
(或boost::optional
),以发出实例创建成功或失败的信号:
template< typename T, typename... Args >
std::optional< T > try_make( Args&&... args )
{
try {
return T{ std::forward< Args >( args )... };
}
catch( ... ) {
return {};
}
}
基本上这样使用:
auto instance = try_make< MyClass >(3, 4, 5);
其中instance
现在是optional<MyClass>
。要测试结果并将实例的可用性与错误情况分开也很简单:
if( auto instance = try_make< MyClass >( 3, 4, 5 ) ) {
// use *instance, but this code is *not* in the try/catch block!
}
else {
// creating the instance failed
}
当然异常信息会丢失,但是您可以选择一个不那么通用的函数,并根据您的需要在catch块中添加一些日志记录。
Remy答案的变体,但使用std::optional
保存动态分配:
std::optional<MyClass> instance_opt;
try {
// could use `instance = MyClass(3, 4, 5)`, but that requires you to write a move constructor
instance_opt.emplace(3, 4, 5);
}
catch (const MyClassException& ex) {
std::cerr << "There was an error creating the MyClass." << std::endl;
return 1;
}
MyClass& instance = *instance_opt;
// use instance as needed...
相关文章:
- 未在作用域中声明unordered_map
- 有没有一种方法可以在编译时获得作用域类名
- C++quit()函数中可能存在作用域问题
- 未在此作用域OpenCV3.4中声明cvSaveImage
- 全局作用域中函数指针的赋值
- 在类函数中初始化外部作用域变量
- 不同作用域中的静态变量和全局变量
- 是同一作用域的函数部分中的函数调用
- 未在此作用域中声明的函数和变量 (C++)
- 类作用域的类型别名"using":[何时]方法中的用法可以先于类型别名?
- 将作用域枚举转换为基础类型
- 表达式必须具有完整或无作用域的枚举图
- 在构造函数中输入对象时C++类成员作用域
- 无法让"std::enable_if"适用于无作用域枚举
- 为什么不能直接引用作用域枚举类成员,而不能为无作用域枚举生成类成员?
- 函数未在作用域中声明 / 如何结合使用 header.h、header.cpp 和 main.cpp?
- 错误:表达式必须具有算术、无作用域枚举或带有运算符重载的指针类型
- 类的堆分配对象是否在其作用域之后但在 C++ 中调用其析构函数之前处于活动状态
- 在释放了所有作用域内指针之后仍然可访问内存
- 从构造函数捕获异常意味着我的实例之后超出了作用域