[英]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;
}
然后,一個類繼承了Listener
並可以向Frobulator
注冊為偵聽Frobulator
。 當Frobulator
一些來電者(不一定聽眾)的調用后frobs,聽眾會被告知。
我真正的問題是,偵聽器是否應該“內部”偵聽,因此需要對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引用(如果不需要,甚至不需要引用), FrobReactor
承認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
,然后第一個方法也可以與非const引用一起使用,但這聽起來像是一種hack。
是否有“正確”的方法來做到這一點?
我不會在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中的某處有一個方法,該方法可以將偵聽器添加到Frobulator中,如下所示:
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);
}
這是一個很小的變化,但是除非有其他原因傳遞指針,否則我只希望在轉讓所有權時傳遞指針。 當然,您必須確保在任何一種情況下都不會刪除您的偵聽器(由於超出范圍)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.