gpt4 book ai didi

c++ - 在设计时未考虑异常安全的方法/类中提供强有力的保证

转载 作者:行者123 更新时间:2023-11-30 04:15:59 24 4
gpt4 key购买 nike

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

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

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

不编译,因为 Trial::operator= 不是编译器默认构建的,因为 Trial::aconst。这非常明显。

现在重点是,先写代码

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 行,整个程序无法编译。

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

最佳答案

显而易见的答案是修改 Trial 使其支持任务也是如此。除此之外,如果唯一的原因是你要支持任务就是提供强有力的保障,您可以实现自己的赋值运算符,最好private,它忽略了基类;因为你知道两个基类将是相同的,不需要分配他们之间。

请注意,强保证比任务。这不会改变问题:你不能交换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 中使用 const 成员吗?实现这个的通常方法是制作 a非常量但私有(private),并且只提供一个 setter/getter 。这意味着Trial::a 实际上是 const,除了 是完整的作业。

关于c++ - 在设计时未考虑异常安全的方法/类中提供强有力的保证,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18013358/

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