c++ - RAII状态管理

标签 c++ c++11 c++14 raii

我需要改变一个状态。然后做事。然后将状态重置为原来的状态 - 例如:

auto oldActivationOrder = mdiArea->activationOrder();
mdiArea->setActivationOrder( QMdiArea::StackingOrder );
mdiArea->cascadeSubWindows();
mdiArea->setActivationOrder( oldActivationOrder );

我如何以 RAII 方式执行此操作? (C++ 11 和/或 14)

编辑:感谢您的所有回答。

有几个创建自定义类来处理状态更改的建议(BoBTFish、mindriot、Mattias Johansson)。这个解决方案看起来很好很清楚。但是,我认为将行数从 4 增加到 20+ 是一个缺点。如果经常使用,这会使代码膨胀。此外,似乎有些地方因为有一个单独的类(class)而丢失了。

Ami Tavory 建议使用 std::unique_ptr。这没有代码膨胀问题并保持局部性。但是,正如 Ami 还指出的那样,它可能不是最具可读性的解决方案。

sp2danny 提出了一个可以重复使用的通用状态更改类。这避免了代码膨胀,前提是它可以替换多个自定义类。我将接受这个答案 - 但我想正确的方法确实取决于上下文。

最佳答案

RAII:R资源A获取II初始化。

这也意味着资源释放就是破坏,尽管我从未见过人们谈论 RRID,尽管这是它更有用的一面。 (也许应该是终止,还是最终确定?)

重点是,您在对象的构造函数中做了一些工作,并在析构函数中有效地反转了它。这意味着无论您如何退出范围,都会执行清理:多个 return,多个 break,抛出异常,...(甚至 转到!)

class ScopedActivationOrderChange {
    QMdiArea&             area_;     // the object to operate on
    QMdiArea::WindowOrder oldOrder_; // save the old state

  public:
    ScopedActivationOrderChange(QMdiArea& area, ActivationOrder newOrder)
        : area_(area)
        , oldOrder_(area_.activationOrder()) // save old state
    {
        area_.setActivationOrder(newOrder); // set new state
    }

    ~ScopedActivationOrderChange()
    {
        area_.setActivationOrder(oldOrder_); // reset to old state
    }
};

// ...

{ // <-- new scope, just to establish lifetime of the change
    ScopedActivationOrderChange orderChange{*mdiArea, QMdiArea::StackingOrder};
    mdiArea->cascadeSubWindows();
} // <-- end of scope, change is reversed

标准库不为此提供任何通用工具。它确实提供了一些用于更具体的用途,例如 std::unique_ptr用于删除动态分配的对象,在某些情况下可以用于其他事情,尽管它有点难看。 std::vector可以看作是动态数组的 RAII 类,还提供一些其他管理工具,但是这个类不太容易被滥用于其他目的。

关于c++ - RAII状态管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35911317/

相关文章:

c++ - 读取部分字符串到整数数组

C++ 存储在堆上保存在堆栈上

c++ - 获取当前线程时间id的操作开销大吗?

c++ - 为什么我不能引用指向实例化对象函数的指针?

c++ - 为什么 Qt Creator 找到了 typedef,但找不到构建过程?

c++ - c++11的线程,用new创建

c++ - g++ -std=c++0x 的意外编译问题

c++ - 什么是广义 lambda 捕获,为什么要创建它?

c++ - 是否可以在 C++ 中使用匿名类?

c++ - 从模板类型而不是参数获取转发类型