监听器 class 继承者 - 对 class 的 const 或非常量引用被监听了?
Listener class inheritor - const or non-const reference to class listened to?
代码库的一个非常常见的模式是这样的 Listener
事件:
class Frobulator
{
public:
class Listener
{
private:
// only frobulators can frob
friend class Frobulator;
virtual void onFrobbed() = 0;
}
void maybeFrob()
{
// assume we always frob, but maybe we only do it sometimes
// and the caller won't know if a call will do it
for (auto& l: listeners)
{
l->onFrobbed();
}
}
void addListener(Listener* l)
{
listeners.push_back(l);
}
private:
std::vector<Listener*> listeners;
}
然后,class继承了Listener
,可以注册为Frobulator
的监听器。当 Frobulator
在某个呼叫者(不一定是听众)的呼叫后出现故障时,将告知听众。
我真正的问题是,监听器是否应该监听 "internally",因此需要对 Frobulator
的非常量引用,但使用 private
Listener
自然?
class FrobReactor: private Frobulator::Listener
{
public:
FrobReactor(Frobulator& frobulator_)
frobulator(frobulator)
{
frobulator.addListener(this);
}
private:
void onFrobbed() override
{
// react!
}
Frobulator& frobulator;
}
// and externally ...
Frobulator theFrobber;
FrobReactor reactor(theFrobber);
theFrobber.maybeFrob();
或者监听器是否应该采用 const-reference(如果你不需要它,甚至不需要引用),承认 FrobReactor
不会修改 Frobulator
,但宣传它它是一个 Frobulator::Listener
并期望客户端代码将其连接起来:
class FrobReactor: public Frobulator::Listener
{
public:
FrobReactor(const Frobulator& frobulator_):
frobulator(frobulator_)
{
}
private:
void onFrobbed() override
{
// react!
}
const Frobulator& frobulator;
}
// and externally
Frobulator theFrobber;
FrobReactor reactor(theFrobber);
theFrobber.addListener(&reactor);
theFrobber.maybeFrob();
或者,addListener
方法可以设为 const,侦听器列表 mutable
然后第一个方法也可以使用非常量引用,但这感觉像是 hack。
是否有 "right" 方法来做到这一点?
我不会在 FrobReactor 中存储对观察到的(或听到的)Frobulator 的引用。相反,我会将对 Frobulator 实例的 const 引用传递给 onFrobbed
方法。
class Listener
{
private:
// only frobulators can frob
friend class Frobulator;
virtual void onFrobbed(const Frobulator& frobulator) = 0;
}
并且,改编maybeFrob
:
void maybeFrob()
{
// assume we always frob, but maybe we only do it sometimes
// and the caller won't know if a call will do it
for (auto& l: listeners)
{
l->onFrobbed(*this);
}
}
至于 addListener 是否应该是 const(因此,侦听器的向量是否应该是可变的),这取决于您要实现的目标。我同意这感觉很老套,但另一方面,如果您想确保 API 的客户只处理 const Frobulators,那么这是一种方法。另一个方法是在你的 API 中的某处有一个方法来处理向 Frobulators 添加侦听器,如下所示:
void addListener(const Frobulator& frobulator, Frobulator::Listener& listener) {
Frobulator& nonConst = // obtain non-const reference to this frobulator
nonConst.addListener(listener);
}
这真的取决于你的设计。否则,如果您只想保护侦听器免于修改 Frobulator,那么将 const 引用传递给 'onFrobbed 方法似乎就足够了。
最后,我会像这样更改 addListener
:
void addListener(Listener& listener)
{
listeners.push_back(&listener);
}
这是一个小改动,但我更喜欢在转让所有权时只传递一个指针,除非有其他原因需要传递一个指针。当然,在任何一种情况下,您都必须确保您的侦听器不会被删除(超出范围)。
代码库的一个非常常见的模式是这样的 Listener
事件:
class Frobulator
{
public:
class Listener
{
private:
// only frobulators can frob
friend class Frobulator;
virtual void onFrobbed() = 0;
}
void maybeFrob()
{
// assume we always frob, but maybe we only do it sometimes
// and the caller won't know if a call will do it
for (auto& l: listeners)
{
l->onFrobbed();
}
}
void addListener(Listener* l)
{
listeners.push_back(l);
}
private:
std::vector<Listener*> listeners;
}
然后,class继承了Listener
,可以注册为Frobulator
的监听器。当 Frobulator
在某个呼叫者(不一定是听众)的呼叫后出现故障时,将告知听众。
我真正的问题是,监听器是否应该监听 "internally",因此需要对 Frobulator
的非常量引用,但使用 private
Listener
自然?
class FrobReactor: private Frobulator::Listener
{
public:
FrobReactor(Frobulator& frobulator_)
frobulator(frobulator)
{
frobulator.addListener(this);
}
private:
void onFrobbed() override
{
// react!
}
Frobulator& frobulator;
}
// and externally ...
Frobulator theFrobber;
FrobReactor reactor(theFrobber);
theFrobber.maybeFrob();
或者监听器是否应该采用 const-reference(如果你不需要它,甚至不需要引用),承认 FrobReactor
不会修改 Frobulator
,但宣传它它是一个 Frobulator::Listener
并期望客户端代码将其连接起来:
class FrobReactor: public Frobulator::Listener
{
public:
FrobReactor(const Frobulator& frobulator_):
frobulator(frobulator_)
{
}
private:
void onFrobbed() override
{
// react!
}
const Frobulator& frobulator;
}
// and externally
Frobulator theFrobber;
FrobReactor reactor(theFrobber);
theFrobber.addListener(&reactor);
theFrobber.maybeFrob();
或者,addListener
方法可以设为 const,侦听器列表 mutable
然后第一个方法也可以使用非常量引用,但这感觉像是 hack。
是否有 "right" 方法来做到这一点?
我不会在 FrobReactor 中存储对观察到的(或听到的)Frobulator 的引用。相反,我会将对 Frobulator 实例的 const 引用传递给 onFrobbed
方法。
class Listener
{
private:
// only frobulators can frob
friend class Frobulator;
virtual void onFrobbed(const Frobulator& frobulator) = 0;
}
并且,改编maybeFrob
:
void maybeFrob()
{
// assume we always frob, but maybe we only do it sometimes
// and the caller won't know if a call will do it
for (auto& l: listeners)
{
l->onFrobbed(*this);
}
}
至于 addListener 是否应该是 const(因此,侦听器的向量是否应该是可变的),这取决于您要实现的目标。我同意这感觉很老套,但另一方面,如果您想确保 API 的客户只处理 const Frobulators,那么这是一种方法。另一个方法是在你的 API 中的某处有一个方法来处理向 Frobulators 添加侦听器,如下所示:
void addListener(const Frobulator& frobulator, Frobulator::Listener& listener) {
Frobulator& nonConst = // obtain non-const reference to this frobulator
nonConst.addListener(listener);
}
这真的取决于你的设计。否则,如果您只想保护侦听器免于修改 Frobulator,那么将 const 引用传递给 'onFrobbed 方法似乎就足够了。
最后,我会像这样更改 addListener
:
void addListener(Listener& listener)
{
listeners.push_back(&listener);
}
这是一个小改动,但我更喜欢在转让所有权时只传递一个指针,除非有其他原因需要传递一个指针。当然,在任何一种情况下,您都必须确保您的侦听器不会被删除(超出范围)。