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-torC
で発生するリソースの割り当てを遅らせたいとします。C
これには、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(),...);
...
}
};