首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >RAII类设计

RAII类设计
EN

Stack Overflow用户
提问于 2012-04-17 11:08:42
回答 2查看 913关注 0票数 0

让我们假设我有一个类,它以RAII方式管理一些资源:

代码语言:javascript
复制
class C
{
   HANDLE hResource_;

   // prevent sharing the ownership over the resource among multiple instances of C
   C(const C&);
   C& operator=(const C&);

public:
   C() : hResource_(INVALID_HANDLE){}

   C(int arg1, const std::string& arg2,...)
   {
      ...
      allocResource(arg1, arg2, ...);
      ...
   }

   ~C
   {
      ...
      FreeResource(hResource_);
      hResource_ = INVALID_HANDLE;
      ...
   }

   void allocResource(int arg1, const std::string& arg2, ...)
   {
      if(hResource_ == INVALID_HANDLE)
      {
          hResource_ = AllocateResource(arg1, arg2,...);
      }
   }

   HANDLE handle() {return hResource_;}
};

它的构造函数接受资源分配所需的一些参数,我能够创建它的一个实例,使用它,并让它驻留在某个范围内:

代码语言:javascript
复制
// some global function 
void goo()
{
   C c(123, "test");
   UseResource(c.handle(),...);
   ... 
}

假设我现在希望C的一个实例成为某个类的成员,并且希望延迟C的c-tor中发生的资源分配,这需要C的默认c-tor和执行资源分配的C的成员函数(例如,调用AllocateResource()allocResource() )。

代码语言:javascript
复制
class A
{
   C c_;

public:
   void foo1()
   {
      ...
      c_.allocResource(123, "test"); 
      UseResource(c_.handle(),...);
      ...
   }   

   void foo2()
   {
      ...         
      UseResource(c_.handle(),...);
      ...
   }   
};

通过使用专用函数,我们以某种我不喜欢的方式公开了C的内部结构。

我的问题是:这种方法是启用延迟初始化的常见方法吗?有其他选择吗?

编辑:--这是关于(MSalters')建议的一个可能的类设计:

代码语言:javascript
复制
class C
{
   HANDLE hResource_;

   // prevent sharing the ownership over the resource 
   // among multiple instances of C
   C(const C&);
   C& operator=(const C&);

public:      

   // prevent object creation if resource cannot be acquired
   C(int arg1, const std::string& arg2,...)
   {          
      hResource_ = AllocateResource(arg1, arg2,...);

      // assumption: AllocateResource() returns 
      // INVALID_HANDLE in case of failure
      if(hResource_ == INVALID_HANDLE)
         throw resource_acquisition_exception();
   }

   ~C
   {
      ...
      FreeResource(hResource_);
      hResource_ = INVALID_HANDLE;
      ...
   }

   HANDLE handle() {return hResource_;}
};

class A
{
   std::unique_ptr<C> c_;

public:
   void foo1()
   {
      try
      {
         ...
         c_ = std::unique_ptr<C>(new C(123, "test"));
         UseResource(c_->handle(),...);
         ...
      }
      catch(const resource_acquisition_exception& exc)
      {
         ...
      }
      catch(...)
      {
         ...
      }
   }   

   void foo2()
   {
      ...         
      UseResource(c_->handle(),...);
      ...
   }   
};
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-04-17 11:24:16

不,这不是做RAII的常见方式。事实上,这根本不是莱伊。如果不能为C分配必要的资源,就不要创建C

票数 4
EN

Stack Overflow用户

发布于 2012-04-17 11:28:13

问题是,您确实公开了C的内部,但是您已经在使用handle()函数来实现这个功能,这已经限制了执行延迟实例化的可能性。

如果C实际上被调用来做一些事情,而不是仅仅得到处理程序,那就更容易了。但是,由于句柄()是一个getter,而且您已经可以在构造函数中传递所需的参数(无需实例化,而是通过存储参数),所以可以签入hResource_ ()是否有效,如果不是,则分配资源(如果分配失败,则抛出异常)。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10190057

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档