在C ++中实现Register / Unregister-Pattern

时间:2009-12-10 14:06:38

标签: c++

我经常遇到一个问题,即我有一个具有一对Register / Unregister-kind-methods方法的类。 e.g:

class Log {
public:
    void AddSink( ostream & Sink );
    void RemoveSink( ostream & Sink );
};

这适用于几种不同的情况,例如观察者模式或相关内容。我担心的是,这有多安全?从previous question我知道,我无法从该引用中安全地获取对象标识。 This approach向调用者返回一个迭代器,它们必须传递给unregister方法,但这会暴露实现细节(迭代器类型),所以我不喜欢它。我可以返回一个整数句柄,但这需要大量额外的内部管理(什么是最小的自由句柄?)。你是怎么做到的?

3 个答案:

答案 0 :(得分:2)

除非客户端对象有两个ostream派生而不使用虚拟继承,否则您是安全的。

简而言之,这就是用户的错误 - 他们不应该以两种不同的方式多次继承接口类。

使用地址并完成。在这些情况下,我采用指针参数而不是引用来明确表示我将存储地址。如果您决定采用const引用,它还可以防止可能启动的隐式转换。

   class Log {
   public:
       void AddSink( ostream* Sink );
       void RemoveSink( ostream* Sink );
   };

您可以创建一个在构造函数中调用AddSink的RAII对象,并在析构函数中创建RemoveSink,以使此模式异常安全。

答案 1 :(得分:0)

您可以使用智能指针管理对象,并在注册/注销功能中比较指针的相等性。

如果您只有堆栈分配的对象永远不会在寄存器和注销调用之间复制,您也可以传递指针而不是引用。

你也可以这样做:

typedef iterator handle_t;

并隐藏这样一个事实,即如果暴露内部数据结构,你会给出内部迭代器。

答案 2 :(得分:0)

在上一个问题中,Konrad Rudolph posted an answe r(您不接受但得分最高),如果您使用基类指针,那么一切都应该没问题。