堆栈对象的C++继承

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)吗?

jan*_*anm 9

您将按值返回令牌.这意味着您没有返回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超出范围时执行各种其他操作.


sha*_*oth 5

你应该从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 可以安全地分配一个空指针 - 它的析构函数将处理这个.

  • +1,或其他智能指针:`std :: tr1 :: scoped_ptr`,`std :: tr1 :: shared_ptr`(或者如果你的编译器不支持tr1,它们的提升替代品) (2认同)