我有一个基类, 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超出范围时进行其他各种操作。

10-07 22:07