kiw*_*ptn 1 c++ inheritance stack mutex locking
我有一个基类Token.它没有实现,因此充当标记接口.这是调用者将使用的类型.
{
Token t = startJob(jobId);
// ... (tasks)
// t falls out of scope, destructors are called
}
Run Code Online (Sandbox Code Playgroud)
我有一个派生类,LockToken.它包裹着互斥锁并确保在施工期间获得锁定并在破坏期间释放锁定.startJob方法是一种工厂方法,它决定是返回令牌(不提供锁定)还是返回LockToken(提供锁定).
Token startJob(int jobId)
{
return (jobId>0) ? LockToken() : Token() ;
}
Run Code Online (Sandbox Code Playgroud)
当startJob返回一个基本实例(令牌)时,一切都运行良好.在另一种情况下(jobId> 0),有一个由派生实例组成的副本到基础实例.在其他工作中,一个不同的Token是从LockToken复制构造的,并且原始的LockToken过早地超出了范围,在startJob的范围内释放了锁.
我怎么摆脱这个?我可以更改startJob以使其返回或输出真正的协变令牌(意味着它可能是一个LockToken)吗?
您将按值返回令牌.这意味着您没有返回LockToken,而是返回从LockToken实例构造的令牌副本.
更好的方法是使用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
}
Run Code Online (Sandbox Code Playgroud)
请注意,您不再需要不执行任何操作的Token类,而LockToken类现在是一个完全对客户端隐藏的实现细节,使您可以在Token超出范围时执行各种其他操作.
你应该从startJob()返回一个指针 - 一个原始指针或一个合适的智能指针.例如:
Token* startJob(int jobId)
{
return (jobId>0) ? new LockToken() : new Token();
}
{
std::auto_ptr<Token> t = startJob(jobId);
// ... (tasks)
// t falls out of scope, destructors are called
}
Run Code Online (Sandbox Code Playgroud)
当auto_ptr超出范围时,它会调用delete包装的指针.
以上解决方案是您的直接改写.正如在这个问题的另一个答案中所提到的,你根本不需要虚拟Token类 - 你只需返回一个空指针:
LockToken* startJob(int jobId)
{
return (jobId>0) ? new LockToken() : 0;
}
{
std::auto_ptr<LockToken> t = startJob(jobId);
// ... (tasks)
// t falls out of scope, destructors are called
}
Run Code Online (Sandbox Code Playgroud)
auto_ptr 可以安全地分配一个空指针 - 它的析构函数将处理这个.