在C++中实现寄存器/取消寄存器模式

问题描述:

我经常遇到这样的问题,即我有一个具有一对Register/Unregister类型方法的类。例如:在C++中实现寄存器/取消寄存器模式

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

这适用于几种不同的情况,如观察者模式或相关的东西。我担心的是,这有多安全?从previous question我知道,我无法安全地从该引用中派生出对象标识。 This approach返回一个迭代器给调用者,他们必须传递给注销方法,但是这暴露了实现细节(迭代器类型),所以我不喜欢它。我可以返回一个整数句柄,但这需要很多额外的内部管理(什么是最小的空闲句柄?)。你如何去做这件事?

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

总之,这是用户的错误 - 它们不应该以两种不同方式两次继承接口类。

使用该地址并完成它。在这些情况下,我使用指针参数而不是参考来明确指出我将存储地址。它还可以防止在您决定采用const引用时可能会触发的隐式转换。

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

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

您可以使用智能指针来管理您的对象,并比较指针在注册/取消注册函数内是否相等。

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

你也可以这样做:

typedef iterator handle_t; 

,并隐瞒事实,你给了内部迭代器,如果暴露内部数据结构你担心。

+0

智能指针用于对象的共享所有权,这里不是这种情况。另外,我认为我引用的其他问题中讨论的内容也适用于智能指针。 – 2009-12-10 14:11:56

+0

对不起,我的糟糕的智能指针与shared_ptr不同,所以请忽略我的评论部分。 – 2009-12-10 14:12:52

+0

答案也发布在其他问题中。只要你比较相同类型的指针(比如ISink),一切都很好。 – Sebastian 2009-12-10 14:18:55

在你之前的问题中,Konrad Rudolph posted an answer(你没有接受但是得分最高),如果你使用了基类指针,那么你应该没问题,你似乎这样做。