c++ - 如果资源获取可能失败,如何实现 RAII

标签 c++ raii

我想借助 RAII 实现一个类。应该在构造函数中获取资源,但有可能获取失败。我将在下面使用 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_;
};

那么,处理 fopen 返回 NULL 时发生的错误的最佳方法是什么?因为它是构造函数,所以我不能返回 NULL。

我希望有人能给我提示如何处理此类错误!

谢谢你,最好的问候,

闪光器

最佳答案

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

相反,析构函数不得抛出异常(如果析构函数在堆栈展开期间抛出异常,则调用 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_);
}

请注意,这段代码有很多错误:fclose 函数可能会失败,失败可能与关闭有关,也可能无关(例如,某些写入错误仅在刷新时报告 close POSIX 系统上的系统调用)。请将 iostreams 用于 C++ 中的文件 I/O,因为它们为这些问题提供了方便的抽象。

关于c++ - 如果资源获取可能失败,如何实现 RAII,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8565463/

相关文章:

C++ 无法通过虚拟基 A 从基 A 转换为派生类型 B

c++ - catch 是否保证在抛出异常后执行?

c++ - size_type 和 multi_array 索引的 Boost 有符号/无符号比较

c++ - 如果我忽略具有 shared_ptr 返回类型的函数的返回值怎么办

c++ - 我应该如何将 C 库包装到 C++ 中

c++ - 返回指向结构的指针,如何自动释放内存?

iphone - 惯用的短生命周期本地对象类似于 RAII

C++ 通过引用局部变量传递

c++ - 指针 vector 和值 vector 之间的差异

c++ - 输出到我找不到的 C++ 文件时出错