【发布时间】:2012-04-17 11:08:42
【问题描述】:
假设我有一个以 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() 调用AllocateResource())。
class A
{
C c_;
public:
void foo1()
{
...
c_.allocResource(123, "test");
UseResource(c_.handle(),...);
...
}
void foo2()
{
...
UseResource(c_.handle(),...);
...
}
};
通过使用专用函数,我们以某种我不喜欢的方式暴露了C 的内部结构。
我的问题是:这种方法是启用延迟初始化的常用方法吗?有其他选择吗?
编辑:这是关于以下(MSalters')建议的可能类设计:
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(),...);
...
}
};
【问题讨论】:
-
实现一个移动构造函数怎么样?这样您就可以在 foo1 中创建一个新的 C 对象并将其分配给 c_。在 c++03 中,您可以通过使用带有 C 非 const 引用的构造函数来做到这一点。
-
您应该将可能的解决方案转化为答案,而不是将其置于问题中。