Chr*_*ews 56 c++ boost-signals
我知道boost.org上的教程解决了这个问题: Boost.org Signals Tutorial,但这些例子并不完整,有些过于简化.那里的例子没有显示包含文件,代码的某些部分有点模糊.
这就是我需要的:
ClassA引发多个事件/信号
ClassB订阅这些事件(多个类可以订阅)
在我的项目中,我有一个较低级别的消息处理程序类,它将事件引发到业务类,该业务类对这些消息进行一些处理并通知UI(wxFrames).我需要知道这些可能是如何连线的(什么顺序,谁叫谁等).
Mat*_*tyT 86
下面的代码是您请求的最小工作示例. ClassA发出两个信号; SigA发送(并接受)没有参数,SigB发送一个int. ClassB有两个函数将cout在调用每个函数时输出.在该示例中,有一个ClassA(a)实例和两个ClassB(b和b2)实例. main用于连接和发射信号.值得一提的是,ClassA和ClassB什么都不知道对方的(即它们不是在编译时绑定).
#include <boost/signal.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost;
using namespace std;
struct ClassA
{
signal<void ()> SigA;
signal<void (int)> SigB;
};
struct ClassB
{
void PrintFoo() { cout << "Foo" << endl; }
void PrintInt(int i) { cout << "Bar: " << i << endl; }
};
int main()
{
ClassA a;
ClassB b, b2;
a.SigA.connect(bind(&ClassB::PrintFoo, &b));
a.SigB.connect(bind(&ClassB::PrintInt, &b, _1));
a.SigB.connect(bind(&ClassB::PrintInt, &b2, _1));
a.SigA();
a.SigB(4);
}
Run Code Online (Sandbox Code Playgroud)
输出:
Foo Bar: 4 Bar: 4
为了简洁起见,我采用了一些你通常不会在生产代码中使用的快捷方式(特别是访问控制是松散的,你通常'隐藏'你的信号注册背后的功能,如KeithB的例子).
似乎大多数困难在于boost::signal习惯使用boost::bind.这是一个有点令人费解的第一!对于一个更为复杂的例子,你也可以使用bind挂钩ClassA::SigA与ClassB::PrintInt即使SigA没有没有发出int:
a.SigA.connect(bind(&ClassB::PrintInt, &b, 10));
Run Code Online (Sandbox Code Playgroud)
希望有所帮助!
Kei*_*thB 11
以下是我们的代码库中的示例.它被简化了,所以我不保证它会编译,但它应该是接近的.Sublocation是你的A类,Slot1是你的B类.我们有很多这样的插槽,每个插槽都订阅不同的信号子集.使用这种方案的好处是Sublocation不知道任何槽的任何内容,并且槽不需要是任何继承层次结构的一部分,并且只需要为它们关心的槽实现功能.我们使用它通过非常简单的界面将自定义功能添加到我们的系统中.
Sublocation.h
class Sublocation
{
public:
typedef boost::signal<void (Time, Time)> ContactSignal;
typedef boost::signal<void ()> EndOfSimSignal;
void endOfSim();
void addPerson(Time t, Interactor::Ptr i);
Connection addSignalContact(const ContactSignal::slot_type& slot) const;
Connection addSignalEndOfSim(const EndOfSimSignal::slot_type& slot) const;
private:
mutable ContactSignal fSigContact;
mutable EndOfSimSignal fSigEndOfSim;
};
Run Code Online (Sandbox Code Playgroud)
Sublocation.C
void Sublocation::endOfSim()
{
fSigEndOfSim();
}
Sublocation::Connection Sublocation::addSignalContact(const ContactSignal::slot_type& slot) const
{
return fSigContact.connect(slot);
}
Sublocation::Connection Sublocation::addSignalEndOfSim(const EndOfSimSignal::slot_type& slot) const
{
return fSigEndOfSim.connect(slot);
}
Sublocation::Sublocation()
{
Slot1* slot1 = new Slot1(*this);
Slot2* slot2 = new Slot2(*this);
}
void Sublocation::addPerson(Time t, Interactor::Ptr i)
{
// compute t1
fSigOnContact(t, t1);
// ...
}
Run Code Online (Sandbox Code Playgroud)
Slot1.h
class Slot1
{
public:
Slot1(const Sublocation& subloc);
void onContact(Time t1, Time t2);
void onEndOfSim();
private:
const Sublocation& fSubloc;
};
Run Code Online (Sandbox Code Playgroud)
Slot1.C
Slot1::Slot1(const Sublocation& subloc)
: fSubloc(subloc)
{
subloc.addSignalContact(boost::bind(&Slot1::onContact, this, _1, _2));
subloc.addSignalEndSim(boost::bind(&Slot1::onEndSim, this));
}
void Slot1::onEndOfSim()
{
// ...
}
void Slot1::onContact(Time lastUpdate, Time t)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)