我经常遇到一个问题,即我有一个具有一对Register / Unregister-kind-methods方法的类。 e.g:
class Log {
public:
void AddSink( ostream & Sink );
void RemoveSink( ostream & Sink );
};
这适用于几种不同的情况,例如观察者模式或相关内容。我担心的是,这有多安全?从previous question我知道,我无法从该引用中安全地获取对象标识。 This approach向调用者返回一个迭代器,它们必须传递给unregister方法,但这会暴露实现细节(迭代器类型),所以我不喜欢它。我可以返回一个整数句柄,但这需要大量额外的内部管理(什么是最小的自由句柄?)。你是怎么做到的?
答案 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(您不接受但得分最高),如果您使用基类指针,那么一切都应该没问题。