gpt4 book ai didi

C++ RAII 管理对象状态的改变和恢复

转载 作者:行者123 更新时间:2023-11-30 02:07:35 25 4
gpt4 key购买 nike

我有一个 foo 类。对 foo 的操作需要调用 foo::open()、一些 foo::write(),并且必须以 foo::close() 调用结束:

#include <iostream>

class foo
{
public:
foo()
{
std::cout << "foo::foo()" << std::endl;
}
~foo()
{
std::cout << "foo::~foo()" << std::endl;
}
void open()
{
std::cout << "foo::open()" << std::endl;
}
void close()
{
std::cout << "foo::close()" << std::endl;
}
void write(const std::string& s)
{
std::cout << "foo::write(" << s << ")" << std::endl;
}
private:
// state that must be retained for entire lifetime of object
};

static void useFoo(foo& my_foo)
{
my_foo.open();
my_foo.write("string1");
my_foo.write("string2");
my_foo.close();
}

int main( int argc, char* argv[] )
{
foo my_foo;
useFoo(my_foo);
useFoo(my_foo);
}

正如预期的那样,这将输出以下内容:

foo::foo()
foo::open()
foo::write(string1)
foo::write(string2)
foo::close()
foo::open()
foo::write(string1)
foo::write(string2)
foo::close()
foo::~foo()

我想为我的类 foo 的用户提供一种方法,确保他们不会忘记调用 foo::close(),并确保在发生异常时调用 foo::close()。我不能使用 foo 的析构函数,因为 foo 必须在 foo::close() 之后继续存在,为下一个 foo::open() 做好准备。

我想到了这个 RAII 实现:

#include <iostream>

class foo
{
public:
class opener
{
public:
explicit opener(foo& my_foo):foo_(my_foo)
{
foo_.open();
};
~opener()
{
foo_.close();
};
private:
foo& foo_;
};
foo()
{
std::cout << "foo::foo()" << std::endl;
}
~foo()
{
std::cout << "foo::~foo()" << std::endl;
}
void open()
{
std::cout << "foo::open()" << std::endl;
}
void close()
{
std::cout << "foo::close()" << std::endl;
}
void write(const std::string& s)
{
std::cout << "foo::write(" << s << ")" << std::endl;
}
opener get_opener()
{
return(opener(*this));
}
private:
// state that must be retained for entire lifetime of object
};


static void useFoo(foo& my_foo)
{
foo::opener my_foo_opener = my_foo.get_opener();
my_foo.write("string1");
my_foo.write("string2");
}

int main( int argc, char* argv[] )
{
foo my_foo;
useFoo(my_foo);
useFoo(my_foo);
}

为简单起见,我没有包括让 foo::opener 类公开 foo::write() 方法的明显改进,尽管在真实对象中我会这样做以防止 write() 之前成为可能一个开放()。

编辑 正如 Nawaz 在下面指出的那样,一个真正的类还需要一个复制构造函数和赋值运算符。

为了确保调用 close(),这似乎有很多样板文件。出现两个问题:

  1. 这是否比强制我类(class)的用户使用 try/catch 更简单?

  2. 有没有更简单的方法来实现我想要的:提供基本的异常保证并确保 close() 始终跟在 open() 之后?

最佳答案

嵌套类 opener 应该实现复制语义,因为如果我正确理解您的意图,编译器生成的默认代码会产生不良结果。

所以请实现复制构造函数和复制赋值。

或者,您可能希望通过声明1 private 来完全禁用复制语义,很像implementation of all standard stream classes .我更喜欢这种方法。

1。请注意,您不需要定义它们。只需在 private 部分声明它们就足够了。

关于C++ RAII 管理对象状态的改变和恢复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7662789/

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