ScopeGuard的有個比較能用的上的地方就是,如果需要退出時執行某個操作,可以和方便的使用,而不需要用try finally。不管裏面是否拋出異常,都會執行到我們必須執行的函數
實現也是利用了構造和析構函數,在構造函數中,將需要調用的函數地址傳入,在析構時調用
class ScopeGuardImplBase
{
/// Copy-assignment operator is not implemented and private.
ScopeGuardImplBase& operator =(const ScopeGuardImplBase&);
protected:
~ScopeGuardImplBase()
{}
/// Copy-constructor takes over responsibility from other ScopeGuard.
ScopeGuardImplBase(const ScopeGuardImplBase& other) throw()
: dismissed_(other.dismissed_)
{
other.Dismiss();
}
template <typename J>
static void SafeExecute(J& j) throw()
{
if (!j.dismissed_)
try
{
j.Execute();
}
catch(...)
{}
}
mutable bool dismissed_;
public:
ScopeGuardImplBase() throw() : dismissed_(false)
{}
void Dismiss() const throw()
{
dismissed_ = true;
}
};
沒有參數的函數指針的實現
template <typename F>
class ScopeGuardImpl0 : public ScopeGuardImplBase
{
public:
static ScopeGuardImpl0<F> MakeGuard(F fun)
{
return ScopeGuardImpl0<F>(fun);
}
~ScopeGuardImpl0() throw()
{
SafeExecute(*this);
}
void Execute()
{
fun_();
}
protected:
ScopeGuardImpl0(F fun) : fun_(fun)
{}
F fun_;
};
也可以出一個全局的工廠構造
template <typename F>
inline ScopeGuardImpl0<F> MakeGuard(F fun)
{
return ScopeGuardImpl0<F>::MakeGuard(fun);
}
多個參數,成員函數都可以類似擴展實現
使用,函數退出時候肯定會執行HasNone()函數了
void DoStandaloneFunctionTests()
{
::Loki::ScopeGuard guard0 = ::Loki::MakeGuard( &HasNone );
}
另外不想執行的話可以通過guard0.Dismiss();放棄