gpt4 book ai didi

c++ - 如何将现有的回调接口(interface)转换为使用 boost 信号和插槽

转载 作者:搜寻专家 更新时间:2023-10-31 00:22:45 24 4
gpt4 key购买 nike

我目前有一个类可以通过回调通知许多其他对象:

class Callback {
virtual NodulesChanged() =0;
virtual TurkiesTwisted() =0;
};

class Notifier
{
std::vector<Callback*> m_Callbacks;

void AddCallback(Callback* cb) {m_Callbacks.push(cb); }
...
void ChangeNodules() {
for (iterator it=m_Callbacks.begin(); it!=m_Callbacks.end(); it++) {
(*it)->NodulesChanged();
}
}
};

我正在考虑将其更改为使用 boost 的信号和槽,因为这将有助于减少被调用者被删除时悬空指针的可能性,等等。然而,就目前而言,boost 的信号似乎更倾向于处理函数对象。调整我的代码以仍然使用回调接口(interface)但使用信号和槽来处理连接和通知方面的最佳方法是什么?

最佳答案

与我的其他答案相比,此解决方案更加通用并且消除了样板代码:

#include <iostream>
#include <boost/bind.hpp>
#include <boost/signal.hpp>

///////////////////////////////////////////////////////////////////////////////
// GENERIC REUSABLE PART FOR ALL SUBJECTS
///////////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------------
template <class CallbackType>
class CallbackInvoker
{
public:
virtual ~CallbackInvoker() {}
virtual void operator()(CallbackType* callback) const {};
};

//-----------------------------------------------------------------------------
template <class CallbackType, class Binding>
class BoundInvoker : public CallbackInvoker<CallbackType>
{
public:
BoundInvoker(const Binding& binding) : binding_(binding) {}
void operator()(CallbackType* callback) const {binding_(callback);}

private:
Binding binding_;
};

//-----------------------------------------------------------------------------
template <class CallbackType>
class CallbackSlot
{
public:
CallbackSlot(CallbackType* callback) : callback_(callback) {}
void operator()(const CallbackInvoker<CallbackType>& invoker)
{invoker(callback_);}

private:
CallbackType* callback_;
};

//-----------------------------------------------------------------------------
template <class CallbackType>
class Subject
{
public:
virtual ~Subject() {}
boost::signals::connection Connect(CallbackType* callback)
{return signal_.connect(CallbackSlot<CallbackType>(callback));}

protected:
template <class Binding> void Signal(const Binding& binding)
{
signal_(BoundInvoker<CallbackType,Binding>(binding));
}

private:
boost::signal<void (const CallbackInvoker<CallbackType>&)> signal_;
};


///////////////////////////////////////////////////////////////////////////////
// THIS PART SPECIFIC TO ONE SUBJECT
///////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
class MyCallback
{
public:
virtual ~MyCallback() {}
virtual void NodulesChanged() =0;
virtual void TurkiesTwisted(int arg) =0;
};

//-----------------------------------------------------------------------------
class FooCallback : public MyCallback
{
public:
virtual ~FooCallback() {}
void NodulesChanged() {std::cout << "Foo nodules changed\n";}
void TurkiesTwisted(int arg)
{std::cout << "Foo " << arg << " turkies twisted\n";}
};

//-----------------------------------------------------------------------------
class BarCallback : public MyCallback
{
public:
virtual ~BarCallback() {}
void NodulesChanged() {std::cout << "Bar nodules changed\n";}
void TurkiesTwisted(int arg)
{std::cout << "Bar " << arg << " turkies twisted\n";}
};

//-----------------------------------------------------------------------------
class MySubject : public Subject<MyCallback>
{
public:
void OnNoduleChanged()
{this->Signal(boost::bind(&MyCallback::NodulesChanged, _1));}
void OnTurkiedTwisted(int arg)
{this->Signal(boost::bind(&MyCallback::TurkiesTwisted, _1, arg));}
};

///////////////////////////////////////////////////////////////////////////////
// CLIENT CODE
///////////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------------
int main()
{
MySubject subject;
FooCallback fooCb;
BarCallback barCb;

subject.Connect(&fooCb);
subject.Connect(&barCb);

subject.OnNoduleChanged();
subject.OnTurkiedTwisted(42);
}

boost::bind 万岁! :-)

关于c++ - 如何将现有的回调接口(interface)转换为使用 boost 信号和插槽,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2997732/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com