这是一种概念问题。
让我们假设我们有一些代码库可以从较高层次上与硬件一起工作,并且整个错误处理机制是由异常实现的。假设我们正在打开/关闭一些阀门。只要该硬件操作具有最终确定程序,我们就需要使用RAII概念。因此,某些foo()过程可能如下所示:
class Valve()
{
public:
Valve()
{
// open valve
}
~Valve()
{
// close valve
// Potential exception here
}
private:
// valve internal stuff
}
void foo()
{
try
{
Valve v;
bar1(v); // <--- throws something
} catch(...)
{
// report error and exit
// it's guaranteed that valve destructor will be called
}
}
这段代码看起来不错,但是我们如何管理在阀门关闭期间可能发生的错误。异常无法离开析构函数。我看到的唯一方法是将错误保留在某些错误存储中,例如:
Valve::~Valve()
{
try
{
// close valve
} catch(...)
{
errorStorage.Add(...);
}
}
但是这种方法很难看。 有什么想法在这种情况下如何处理?当然,一种方法是根本不使用异常,而是使用返回码方法和一些清除操作(在出错时使用goto)。 / p>
上: 本来我想避免这种逻辑重复:
void foo()
{
try
{
Valve v;
v.open(); // <- could throw
bar1(v); // <- could throw
v.close(); // <- could throw
} catch(...)
{
if(v.opened())
v.close(); // kind of logic duplication
}
}
答案 0 :(得分:0)
另一种方法是让析构函数直接处理错误。
Valve::~Valve()
{
try
{
// close valve
} catch(...)
{
// handle valve close error
}
}
诚然,有人可能会提出一个案例,这是不合适的,但是这个问题缺少这种确定的细节。 (如果要找到各种答案,则缺少这些细节可能是一件好事。毕竟,这被自我描述为“概念问题”。)简单记录哪个阀门未能关闭是这种情况的一种情况。应该可以。
总的来说,我希望这种方法可以简化代码整体,因为阀门关闭错误的处理已被定位为Valve
类。使用Valve
类的代码不需要知道可以关闭阀门,而不必知道关闭阀门时会发生错误,从而改善了数据封装。
自然,此方法确实要求处理阀关闭错误的代码不会引发异常。 (无论如何,这可能是一个好目标,因为它是错误处理的一部分。)
将错误添加到某种错误存储中的计划对我来说似乎是可疑的。我看到“添加”,我认为“可能分配内存”,这意味着“如果内存用完,可能会引发异常”。因此,我想知道是否已采取措施防止此机制抛出异常,而该机制应该延迟异常的抛出。这是否解决了问题,或者只是降低了可能性?