我有一个程序负责读取数据,格式化和创建记录,以及将记录输出到文件。这次讨论的重要课程是:
FileManager
在正常进程关闭期间,将调用这些类的析构函数,这会导致所有剩余记录被刷新到当前输出文件,然后它将被关闭。这可以确保我们不会丢失任何数据。
但是,在错误情况下,我们需要关闭但我们不想刷新和关闭文件,因为数据可能已损坏。通常情况下会抛出一个异常,它会被RecordGenerator
捕获,然后决定这是否是一个致命的错误。如果是,它将启动应用程序关闭。此时FileManager
被破坏,但需要知道是否有错误。同样,当FileManager
被破坏时,这会导致OutputFile
被破坏,这也需要知道是否有错误。
我的第一反应是添加一些为这些类设置错误标志的公共函数,因此RecordGenerator
可以调用FileManager::setErrorFlag()
,然后可以调用OutputFile::setErrorFlag()
。添加这些链似乎是一种非常难闻的气味,特别是如果你认为对象链可能比这长得多。
有没有更好的方法来处理这种情况?
答案 0 :(得分:1)
当人们开始以不应该使用的方式使用RAII时,这是一个典型的问题。析构函数应该清理资源并恢复它们所负责的任何内容。他们应该不提交更改。典型的异常安全C ++代码如下所示:
例如:
X& X::operator = (const X& x)
{
X y(x); // allocate
this->swap(y); // commit
return *this;
}
void f()
{
Transaction t(...); // begin transaction
// operate
t.commit(); // commit transaction
}
void g()
{
File f(...); // open file
// write to file
f.flush(); // flush the buffers, this may throw but not f.~File()
}