假设我有一个autolocker类,看起来像这样:
template <T>
class autolocker {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
~autolocker() {
lock->unlock();
}
private:
autolocker(const autolocker&);
autolocker& operator=(const autolocker&);
private:
T *lock;
};
Run Code Online (Sandbox Code Playgroud)
显然,目标是能够将此autolocker与任何具有锁定/解锁方法的东西一起使用,而无需借助虚拟功能.
目前,它很简单,使用如下:
autolocker<some_lock_t> lock(&my_lock); // my_lock is of type "some_lock_t"
Run Code Online (Sandbox Code Playgroud)
但这样做是违法的:
autolocker lock(&my_lock); // this would be ideal
Run Code Online (Sandbox Code Playgroud)
反正有没有得到模板类型演绎与此相关(保持在我的autolocker是不可复制的).或者只是指定类型最简单?
是的,你可以使用范围保护技术
struct autolocker_base {
autolocker_base() { }
protected:
// ensure users can't copy-as it
autolocker_base(autolocker_base const&)
{ }
autolocker_base &operator=(autolocker_base const&)
{ return *this; }
};
template <T>
class autolocker : public autolocker_base {
public:
autolocker(T *l) : lock(l) {
lock->lock();
}
autolocker(const autolocker& o)
:autolocker_base(o), lock(o.lock)
{ o.lock = 0; }
~autolocker() {
if(lock)
lock->unlock();
}
private:
autolocker& operator=(const autolocker&);
private:
mutable T *lock;
};
Run Code Online (Sandbox Code Playgroud)
然后编写一个创建自动锁定器的函数
template<typename T>
autolocker<T> makelocker(T *l) {
return autolocker<T>(l);
}
typedef autolocker_base const& autolocker_t;
Run Code Online (Sandbox Code Playgroud)
然后你可以这样写:
autolocker_t lock = makelocker(&my_lock);
Run Code Online (Sandbox Code Playgroud)
一旦const引用超出范围,就会调用析构函数.它不需要是虚拟的.至少GCC 很好地优化了这一点.
遗憾的是,这意味着您必须使您的储物柜对象可以复制,因为您需要从制造商函数返回它.但旧对象不会尝试解锁两次,因为它的指针在被复制时设置为0,所以它是安全的.