Edit:正如 j_random_hacker 所指出的,可以强制用户声明一个命名对象以获取锁。
但是,即使您的类以某种方式禁止创建临时对象,用户也可能会犯类似的错误:
// take out a lock:
if (m_multiThreaded)
{
CSingleLock c(&m_criticalSection, TRUE);
}
// do other stuff, assuming lock is held
最终,用户必须了解他们编写的一行代码的影响。在这种情况下,他们必须知道他们正在创建一个对象,并且必须知道它能持续多久。
另一个可能的错误:
CSingleLock *c = new CSingleLock(&m_criticalSection, TRUE);
// do other stuff, don't call delete on c...
这会导致您问“有什么方法可以阻止我的类的用户在堆上分配它”吗?答案是一样的。
在 C++0x 中,还有另一种方法可以完成这一切,即使用 lambda。定义一个函数:
template <class TLock, class TLockedOperation>
void WithLock(TLock *lock, const TLockedOperation &op)
{
CSingleLock c(lock, TRUE);
op();
}
该函数捕获了 CSingleLock 的正确用法。现在让用户这样做:
WithLock(&m_criticalSection,
[&] {
// do stuff, lock is held in this context.
});
这对于用户来说更难搞砸。语法一开始看起来很奇怪,但是 [&] 后面跟着一个代码块意味着“定义一个不带参数的函数,如果我通过名称引用任何东西,并且它是外部东西的名称(例如,包含的局部变量)函数)让我通过非常量引用访问它,这样我就可以修改它。)