RAII类设计

时间:2012-04-17 11:08:42

标签: c++ raii

假设我有一个以RAII方式管理某些资源的类:

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_;}
};

它的构造函数需要一些资源分配所需的参数,我可以创建它的一个实例,使用它并让它存在于某个范围内:

// some global function 
void goo()
{
   C c(123, "test");
   UseResource(c.handle(),...);
   ... 
}

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

AllocateResource()

通过使用专用函数,我们以某种我不喜欢的方式暴露class A { C c_; public: void foo1() { ... c_.allocResource(123, "test"); UseResource(c_.handle(),...); ... } void foo2() { ... UseResource(c_.handle(),...); ... } }; 的内部。

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


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

C

2 个答案:

答案 0 :(得分:4)

不,这不是做RAII的常用方法。事实上,它根本不是RAII。如果您无法为C分配必要的资源,请不要创建C

答案 1 :(得分:1)

问题确实是你暴露了C的内部,但是你已经使用handle()函数做了这个,这已经限制了进行延迟实例化的可能性。

如果C实际上被调用来执行某些操作而不仅仅是获取处理程序会更容易。但是,由于handle()是一个getter,你可以在构造函数中传递所需的参数(没有实例化,但是通过存储参数),你可以检查handle()hResource_是否有效,如果没有,则分配资源(如果分配失败,则抛出异常。)