我有一些看起来有点像这样的代码:
void writeToStream( std::ostream & outputStream ) { MyXmlWriter xmlWriter{ outputStream }; xmlWriter.addNode(); xmlWriter.addNode(); xmlWriter.close(); // should this be called in `MyXmlWriter` destructor? }
close函数会写一些xml关闭标记,以便正确解析文件.构造函数编写xml文件的标头.人们可以考虑xmlWriter.close();
清理代码.C++的常见建议是将清理代码放入析构函数中.这样你就永远不会忘记清理干净.但是,在我们的例子中,清理代码可能会抛出.(想象一下,file
可能启用了异常,对文件的写入可能会失败.)因此,如果close()
在析构函数中调用该函数,那么它应该包装在try-catch块中,该块会占用抛出的所有异常:
MyXmlWriter::~MyXmlWriter() { try { close(); } catch (...) { } }
但是,在这种情况下,呼叫者不会收到有关任何错误的通知.该函数writeToStream()
可能无法将关闭的xml标记写入文件,而调用者不知道它.在这种情况下,最佳做法是什么?
吞咽异常通常是"最糟糕的做法",因为它违背了首先投掷的目的.
但在这种情况下,你真的只想要析构函数中的一部分功能,不包括刷新,这是一个"奖励",但却有可能抛出.尝试冲洗可能仍然存在副作用,例如不必要地等待已经发生的网络超时.
正如James Kanze所提到的,最佳做法是在析构函数运行之前手动刷新,这排除了析构函数中的异常情况.
将来,C++可能会更好地支持事务.但就目前而言,您的方法是合理的.在任何情况下,它std::filebuf
都是指定析构函数的工作方式:
效果:销毁类的对象
basic_filebuf<charT,traits>
.打电话close()
.如果在销毁对象期间发生异常(包括调用)close()
,则会捕获异常但不会重新抛出异常(参见17.6.5.12).