我有一个基类, token 。它没有实现,因此可以作为标记接口(interface)。这是 call 者将使用的类型。
{
Token t = startJob(jobId);
// ... (tasks)
// t falls out of scope, destructors are called
}
我有一个派生类LockToken。它包裹着一个互斥锁,并确保在构造过程中获得该锁,并在破坏过程中将其释放。从决定是否返回Token(不提供锁定)或LockToken(提供锁定)的意义上来说,startJob方法是一种工厂方法。
Token startJob(int jobId)
{
return (jobId>0) ? LockToken() : Token() ;
}
当startJob返回基本实例( token )时,一切正常。在另一种情况下(jobId> 0),存在将派生实例复制到基本实例的副本。在其他Workds中,从LockToken复制构造了另一个Token,并且原始LockToken太早脱离作用域,从而在startJob范围内释放了锁定。
我该如何摆脱呢?我可以更改startJob使其返回或输出真正的协变 token (这可能是一个LockToken)吗?
最佳答案
您正在按值返回 token 。这意味着您不是在返回LockToken,而是从LockToken实例构造的Token副本。
更好的方法是使用boost::shared_ptr。这样,您的客户就可以复制内容,而不必担心删除。像这样:
#include <boost/shared_ptr.hpp>
typedef boost::shared_ptr<void> Token;
Token startJob(int jobId)
{
if (jobId < 1) return shared_ptr<void>();
return shared_ptr<void>(new LockToken);
}
void use_it()
{
Token t = startJob(jobId);
// ....
// Destructors are called
}
请注意,您不再需要什么都不做的Token类,并且LockToken类现在是一个实现细节,对客户端完全隐藏了,这样您就可以在Token超出范围时进行其他各种操作。