1

我有一个设计问题。让我们首先说这段代码

struct Trial{
    const double a;
    Trial(double a_) : a(a_){}
};

int main(){
    Trial t1(1.);
    Trial t2(2.);
    t1 = t2;
}

不编译,因为Trial::operator=默认情况下不是编译器构建的,因为Trial::ais const. 这很明显。

现在的重点是,代码优先

struct Trial{
    const double a;
    Trial(double a_) : a(a_){}
};

struct MyClass : private Trial{
    MyClass(double a_) : Trial(a_), i(0) {};
    void wannaBeStrongGuaranteeMemberFunction(){
        MyClass old(i);
        bool failed = true;
        //... try to perform operations here
        if(failed)
            *this = old;
    }
    unsigned int i;
};

int main(){
    MyClass m1(1.);
    m1.wannaBeStrongGuaranteeMemberFunction();
}

我需要为类的某些方法提供强大的异常安全性,这些方法派生自Trial. 此类方法对无穷无尽的一系列成员(在示例中)执行无穷无尽的一系列操作i,这使得“手动”恢复操作变得不切实际。因此,我决定最好复制整个课程并在任何失败时将其复制回来。

小括号,代码只是一个例子。遗留的真实世界代码中的一切都复杂得多。在这个例子中,复制就i可以了,但在实际代码中并非如此。此外,这些操作有多个(和复杂的)执行路径,因此将它们“读取”为“事务”会很痛苦。此外,我正在使用范围保护来实现这一点,因此可以在真实代码中正确管理异常。

当然整个事情都没有编译,因为*this = old.

您将如何解决问题/解决问题?

4

1 回答 1

2

显而易见的答案是进行修改Trial,使其也支持分配。除此之外,如果您想要支持赋值的唯一原因是提供强有力的保证,您可以实现自己的赋值运算符,最好是私有的,它忽略了基类;由于您知道这两个基类是相同的,因此无需在它们之间进行分配。

请注意,强保证更多地涉及交换而不是分配。这并没有改变问题:你也不能交换两个版本Trial。你很可能会有类似的东西:

class MyClass : private Trial
{
    class Protected
    {
        bool myCommitted;
        MyClass* myOwner;
        MyClass myInstance;
    public:
        MyClass( MyClass& owner )
            : myCommitted( false )
            , myOwner( &owner )
            , myInstance( owner )
        {
        }
        ~MyClass()
        {
            if ( myCommitted ) {
                myOwner->swap( myInstance );
            }
        }
        MyClass& instance() { return myInstance; }
        void commit() { myCommitted = true; }
    };

public:

    void protectedFunc()
    {
        Protected p( *this );
        p.instance().unprotecedVersionOfFunc();
        //  ...
        p.commit();
    }

任何异常都会使对象保持不变。(当然,您可以反转逻辑,对 进行修改this,如果未提交则交换。)这样做的好处是您还可以“撤消”内存分配等方面的任何更改。

最后:你真的想在Trial. 实现这一点的通常方法是使a 非常量但私有,并且只提供一个吸气剂。这意味着它Trial::a实际上是 const,除了完全赋值。

于 2013-08-02T10:06:23.660 回答