如果资源获取可能失败,如何实施RAII

fer*_*ith 1 c++ raii

我想在RAII的帮助下实现一个课程.资源应该在构造函数中获取,但是acquistition可能会失败.我将在下面使用FILE给出一个示例:

class file {
public:
    file(const char* filename) {
        file_ = fopen(filename, "w+");
        if(!file_) {
          // Okay
        }
        else {
          // ERROR
        }
    }

    ~file() {
        if (fclose(file_)) {
           // ERROR
        }
    }

    void write(const char* str) {
        if (EOF == fputs(str, file_)) {
            throw runtime_error("file write failure");
        }
    }
private:
    FILE* file_;
};
Run Code Online (Sandbox Code Playgroud)

那么,如果fopen返回NULL,那么处理错误的最佳方法是什么?因为它是构造函数,所以我也无法返回NULL.

我希望有人能给我一个如何处理这些错误的提示!

谢谢您最好的问候,

闪光

Ale*_* C. 6

构造函数报告失败的唯一方法是抛出异常.

相反,析构函数不能抛出异常(如果在堆栈展开期间抛出析构函数,std::terminate则调用它,默认情况下结束程序).

如果破坏失败,你可以

  • 静静地吞下错误
  • 中止该计划
  • 记录错误并执行上述任一操作.

如果正确使用RAII,异常可以在不损坏的情况下遍历代码.

这里的例子:

#include <cerrno>
#include <cstring>
#include <sstream>

file::file(const char* filename) 
{
    file_ = fopen(filename, "w+");

    if (!file_)
    {
        std::ostringstream os;
        os << "Cannot open " << filename << ": "
           << std::strerror(errno);

        throw std::runtime_error(os.str());
    }
}

file::~file()
{
    fclose(file_);
}
Run Code Online (Sandbox Code Playgroud)

请注意,此代码有许多错误:fclose函数可能会失败,并且失败可能与关闭有关,也可能与关闭有关(例如,只有close在POSIX系统上的系统调用时刷新时才会报告某些写入错误).请使用iostreams在C++中进行文件I/O,因为它们提供了对这些问题的方便抽象.