gpt4 book ai didi

c++ - 如何处理 RAII 的构造函数失败

转载 作者:IT老高 更新时间:2023-10-28 12:40:38 25 4
gpt4 key购买 nike

我熟悉 RAII 的优点,但我最近在这样的代码中遇到了一个问题:

class Foo
{
public:
Foo()
{
DoSomething();
...
}

~Foo()
{
UndoSomething();
}
}

一切正常,除了构造函数 ... 部分中的代码引发了异常,导致 UndoSomething() 从未被调用。

有一些明显的方法可以解决该特定问题,例如将 ... 包装在 try/catch block 中,然后调用 UndoSomething(),但是:这是重复的代码和 b: try/catch block 是我尝试通过使用 RAII 技术避免的代码异味。而且,如果涉及多个 Do/Undo 对,代码可能会变得更糟,更容易出错,我们必须中途清理。

我想知道有更好的方法来做到这一点 - 也许一个单独的对象接受一个函数指针,并在它被破坏时调用该函数?

class Bar 
{
FuncPtr f;
Bar() : f(NULL)
{
}

~Bar()
{
if (f != NULL)
f();
}
}

我知道这不会编译,但它应该显示原理。 Foo 然后变成...

class Foo
{
Bar b;

Foo()
{
DoSomething();
b.f = UndoSomething;
...
}
}

请注意, foo 现在不需要析构函数。这听起来是不是比它的值(value)更麻烦,还是这已经是一种常见的模式,可以在 boost 中为我处理繁重的工作?

最佳答案

问题是你的类(class)试图做的太多了。 RAII的原理是获取一个资源(要么在构造函数中,要么在后面),析构函数释放;该类的存在只是为了管理该资源。

在您的情况下,除了 DoSomething()UndoSomething() 以外的任何事情都应该是类用户的责任,而不是类本身。

正如 Steve Jessop 在评论中所说:如果您有多个资源要获取,那么每个资源都应该由其自己的 RAII 对象管理;并且将它们聚合为另一个类的数据成员,依次构造它们可能是有意义的。然后,如果任何一次获取失败,之前获取的所有资源都会被各个类成员的析构函数自动释放。

(另外,请记住 Rule of Three ;您的类需要防止复制,或者以某种合理的方式实现它,以防止多次调用 UndoSomething())。

关于c++ - 如何处理 RAII 的构造函数失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11346152/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com