是否可以毫无例外地进行 RAII?
Is it possible to do RAII without exceptions?
如果在构建对象时需要获取的资源可能会失败,如果本地编码标准禁止例外情况,是否可以执行 RAII?
如果是这样,在这种情况下处理资源获取失败的规范方式是什么?
您始终可以创建 bool valid(void)
方法。然后构造函数可以设置适当的条件,在您的代码中,您可以在构造后检查这是否有效。
class foo
{
public:
foo(const char *Filename)
{
mValid = false;
if(fopen(Filename) == NULL)
return;
mValid = true;
}
bool valid(void) { return mValid; }
private:
bool mValid;
};
void myfunc(void)
{
foo fl("myfile");
if(!fl.valid())
{
printf("Error\n");
return;
}
}
我通常不会采用无效对象方法,因为我认为这是糟糕的设计。构造之后,对象必须处于不变量已建立的状态(这是构造函数应该服务的唯一目的)。考虑一个 class strange_vector
实现类似 std::vector
的东西,但是在调用 strange_vector<int>(10, 0)
之后,对象将处于不可用状态,因为分配失败。
相反,我会将构造函数声明为私有并使用 returns 可选的工厂方法:
class file
{
public:
~file() {fclose(m_file);}
static std::optional<file> open(std::string const& filename)
{
auto f = fopen(filename.c_str(), "r");
if (f)
{
return std::make_optional<file>(f);
}
else
{
return std::nullopt;
}
}
private:
file(FILE* file);
FILE* m_file;
};
异常处理的最大好处之一是(除了解耦错误处理和正常代码路径之外)您不能意外地忽略它们。如果需要,您可以创建自己的 class 类似于 optional
,当未使用有效对象初始化时,记录一条错误消息并终止您的程序(或任何其他合理的错误处理)。我认为有一个 talk from A. Alexandrescu about systematic error handling,他实现了一个 class Expected<T>
,其中包含一个 T
类型的值或一个异常。您可以以此为基础,而不是在异常中添加您的错误处理。
std::optional
还不是标准的一部分,但您可以轻松地在最近的编译器、boost 或其他库中获得实现。
如果在构建对象时需要获取的资源可能会失败,如果本地编码标准禁止例外情况,是否可以执行 RAII?
如果是这样,在这种情况下处理资源获取失败的规范方式是什么?
您始终可以创建 bool valid(void)
方法。然后构造函数可以设置适当的条件,在您的代码中,您可以在构造后检查这是否有效。
class foo
{
public:
foo(const char *Filename)
{
mValid = false;
if(fopen(Filename) == NULL)
return;
mValid = true;
}
bool valid(void) { return mValid; }
private:
bool mValid;
};
void myfunc(void)
{
foo fl("myfile");
if(!fl.valid())
{
printf("Error\n");
return;
}
}
我通常不会采用无效对象方法,因为我认为这是糟糕的设计。构造之后,对象必须处于不变量已建立的状态(这是构造函数应该服务的唯一目的)。考虑一个 class strange_vector
实现类似 std::vector
的东西,但是在调用 strange_vector<int>(10, 0)
之后,对象将处于不可用状态,因为分配失败。
相反,我会将构造函数声明为私有并使用 returns 可选的工厂方法:
class file
{
public:
~file() {fclose(m_file);}
static std::optional<file> open(std::string const& filename)
{
auto f = fopen(filename.c_str(), "r");
if (f)
{
return std::make_optional<file>(f);
}
else
{
return std::nullopt;
}
}
private:
file(FILE* file);
FILE* m_file;
};
异常处理的最大好处之一是(除了解耦错误处理和正常代码路径之外)您不能意外地忽略它们。如果需要,您可以创建自己的 class 类似于 optional
,当未使用有效对象初始化时,记录一条错误消息并终止您的程序(或任何其他合理的错误处理)。我认为有一个 talk from A. Alexandrescu about systematic error handling,他实现了一个 class Expected<T>
,其中包含一个 T
类型的值或一个异常。您可以以此为基础,而不是在异常中添加您的错误处理。
std::optional
还不是标准的一部分,但您可以轻松地在最近的编译器、boost 或其他库中获得实现。