当前位置:  开发笔记 > 编程语言 > 正文

正确替换C++中缺少的'finally'

如何解决《正确替换C++中缺少的'finally'》经验,为你挑选了3个好方法。

由于finally在C++中没有,你必须使用RAII设计模式,如果你希望你的代码是异常安全的.一种方法是使用像这样的本地类的析构函数:

void foo() {
    struct Finally {
        ~Finally() { /* cleanup code */ }
    } finalizer();
    // ...code that might throw an exception...
}

与直接解决方案相比,这是一个很大的优势,因为您不必编写清理代码2次:

try {
    // ...code that might throw an exception...
    // cleanup code (no exception)
} catch (...) {
    // cleanup code (exception)
    throw;
}

本地类解决方案的一大缺点是您无法直接访问清理代码中的局部变量.因此,如果您需要访问它们,它会使您的代码膨胀很多,无论如何:

void foo() {
    Task* task;
    while (task = nextTask()) {
        task->status = running;
        struct Finally {
            Task* task;
            Finally(Task* task) : task(task) {}
            ~Finally() { task->status = idle; }
        } finalizer(task);
        // ...code that might throw an exception...
    }
}

所以我的问题是:是否有一个结合了两个优点的解决方案?这样你a)不必编写重复的代码和b)可以访问清理代码中的局部变量,就像task在上一个例子中一样,但没有这样的代码膨胀.



1> Sébastien Ro..:

struct Finally您可以在类的函数中提取清理代码而不是定义,Task并使用Loki的ScopeGuard.

ScopeGuard guard = MakeGuard(&Task::cleanup, task);

有关ScopeGuards的更多信息,另请参阅DrDobb的这篇文章和另一篇文章.



2> Pieter..:

我不认为有更清洁的方法来实现你想要做的事情,但我认为你的例子中"最终方法"的主要问题是不正确的关注点分离.

例如,函数foo()负责Task对象的一致性,这很少是一个好主意,Task本身的方法应该负责将状态设置为合理的.

我确实有时候真的需要最终,而你的代码显然只是一个简单的例子来展示一个观点,但这些情况很少见.在极少数情况下,我可以接受一些更人为的代码.

我想说的是,你应该很少需要最终的结构,而对于你做的少数情况,我会说不要浪费时间去构建一些更好的方法.它只会鼓励你最终使用超过你真正应该...



3> Martin York..:

这是一种如此丑陋的方式:(你来自Java吗?)

请阅读这篇文章:
C++是否支持'finally'块?(我听到的'RAII'是什么?)

它解释了为什么最终是这样一个丑陋的概念,以及为什么RIAA更优雅.

推荐阅读
路人甲
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有