在 Wikipedia 上文件 I/O 的 RAII 的典型示例中,关闭文件时发生的任何错误都会被吞没:
#include <iostream>
#include <string>
#include <fstream>
#include <stdexcept>
void write_to_file (const std::string & message) {
// try to open file
std::ofstream file("example.txt");
if (!file.is_open())
throw std::runtime_error("unable to open file");
// write message to file
file << message << std::endl;
// file will be closed when leaving scope (regardless of exception)
}
file
自动关闭时似乎无法确定是否发生错误;显然,只能file.rdstate()
在file
范围内调用。
我可以file.close()
手动调用,然后检查错误,但我必须在从范围返回的每个地方都这样做,这违背了 RAII 的目的。
一些人评论说,在析构函数中只会发生文件系统损坏等不可恢复的错误,但我不认为这是真的,因为 AFAIK 析构函数在关闭文件之前会刷新文件,并且在刷新时可能会发生可恢复的错误。
那么有没有一种常见的 RAII 方法来获取销毁期间发生的错误?我读到从析构函数中抛出异常是危险的,所以这听起来不像是正确的方法。
我能想到的最简单的方法是注册一个回调函数,如果在销毁期间发生任何错误,析构函数将调用该回调函数。令人惊讶的是,似乎并没有为此提供支持的事件ios_base::register_callback
。这似乎是一个重大的疏忽,除非我误解了什么。
但也许回调是现代类设计中在销毁期间获得错误通知的最常见方式?
我假设在析构函数中调用任意函数也是危险的,但也许将调用包装在一个try/catch
块中是完全安全的。