我遇到了需要臨時更改類實例變量的類實例函數,然後在函數完成時將其恢復。該函數在所有地方都有return語句,並且在每次返回之前都有一個恢復語句。這對我來說似乎很混亂,更不用說提出異常時可怕了。使用堆棧將成員變量重置爲原始值的一般方法?
作爲一種改進,我想出了使用內部類定義的泛化。這是一個示例驅動程序(類恢復器)。
class Unwind {
private:
bool b_active_; ///< the thing I want to be restored
template<typename T>
class restorer {
T* ref_;
T save_;
public:
restorer(T* perm) : ref_(perm), save_(*ref_) {};
~restorer() { *ref_ = save_; }
};
public:
Unwind() : b_active_(false) {};
void a() { out("a in"); b(); out("a end"); }
void b() {
out("b in");
{
restorer<bool> trust_in_the_stack(&b_active_); // "restorer" created on the stack
b_active_ = true; // change b_active_ only while "within" b()
c();
out("b inner end");
}
out("b end");
}
void c() { out("c in"); d(); out("c end"); }
void d() { out("d in"); cout << "deepest" << endl; out("d end"); }
void out(const std::string& msg) {
std::cout << msg << ": " << b_active_ << std::endl;
}
};
int main() { Unwind u; u.a(); return 0; }
使用克++ 4.2.3(-Wall)輸出是:
a in: 0 b in: 0 c in: 1 d in: 1 deepest d end: 1 c end: 1 b inner end: 1 b end: 0 a end: 0
這正是我期望在 「B端」。
我覺得在類Unwind中定義類恢復器有助於防止濫用。
我的問題是,是否有一個通用和安全的方法來做到這一點? 我很擔心有生之年的問題。
編輯:請假定堆棧上沒有線程,而是根據此b_active_標誌更改行爲的「下游」方法。
我認爲最好用save _(* perm)替換初始化列表中的save _(* ref_)。保存_(* ref_)可能會咬你有一天,當有人改變你的課堂上的聲明順序。 – 2008-10-17 01:24:02