【问题标题】:Immediately calling destructor after setting in the fluent interface in C++ [closed]在C ++中的流畅界面中设置后立即调用析构函数[关闭]
【发布时间】:2021-03-04 22:07:13
【问题描述】:

我想创建一个仅用于设置函数参数的类。 我为此使用了流畅的界面。 一些函数返回对象设置参数,真正的代码将在这个对象的析构函数中执行。

首先,这是个好主意吗?当我有很多参数时,这是提高代码可读性的常用方法吗?或者也许我应该使用另一种方式来做到这一点?我很乐意就此提供建议。

如果没问题,如何防止意外将对象保存到局部变量?在这种情况下,析构函数将在变量作用域的末尾被调用。

例子:

class MyClass {
public:
    ~MyClass() noexcept {
        // some code to execute immediately after setting params A and B
    }

    // abstract setting methods
    MyClass &SetA() { return *this; }
    MyClass &SetB() { return *this; }
};

MyClass SomeFunction() {
    return MyClass();
}

int main() {
    // Correct usage:
    SomeFunction()
            .SetA()
            .SetB();
    // destructor here

    // I want to prevent it:
    auto my_class = SomeFunction();
    my_class
            .SetA()
            .SetB();

    {
        auto my_class2 = SomeFunction();
        my_class2
                .SetA()
                .SetB();
        // destructor of `my_class2` here
    }

    // destructor of `my_class` here.
    return 0;
}

【问题讨论】:

标签: c++ oop destructor fluent-interface


【解决方案1】:

一般来说,如果你想强制即使发生异常也发生某些事情,析构函数是一个好地方(但请注意,destructros 默认声明为noexcept(true))。

我个人将它用于“最终”块(使用noexcept(false))。但通常在 C++ 中,由于 RAII,您不需要 finally

我认为您无法阻止生命周期延长/局部变量。而且我们没有属性[[discard]],只有[[nodiscard]]

但是为什么你不在 SetA() 中进行工作呢?对我来说会更清楚吗?

一个很好的理由是如果您需要所有参数数据来完成工作......

更新

只有一种选择。您可以使您的对象不可复制/不可移动:

    MyClass() = default;
    MyClass(const MyClass&) = delete;
    MyClass(MyClass&&) = delete;

但是通过这种方法,您不能拥有像“SomeFunction”这样的东西。当然,这样的工厂函数也可能导致调用你的析构函数的副本。


作为一个建议,我会简单地明确说明:

SomeFunction()
            .SetA()
            .SetB()
            .Exec()
;

【讨论】:

  • 我相信不能保证Exec() 会被最后调用。
  • 不保证,不保证的是参数的求值顺序……
  • For reference。也许更新答案以包含此内容。
猜你喜欢
  • 2013-04-16
  • 1970-01-01
  • 2017-09-03
  • 2014-09-18
  • 1970-01-01
  • 2016-03-02
  • 2023-03-18
  • 2020-06-20
  • 2012-02-10
相关资源
最近更新 更多