使用 Boost::Signals for C++ Eventing 的完整示例
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/768351/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Complete example using Boost::Signals for C++ Eventing
提问by Chris Andrews
I'm aware of the tutorial at boost.org addressing this: Boost.org Signals Tutorial, but the examples are not complete and somewhat over simplified. The examples there don't show the include files and some sections of the code are a little vague.
我知道 boost.org 上的教程解决了这个问题: Boost.org Signals Tutorial,但这些示例并不完整,而且有些过于简化。那里的示例没有显示包含文件,并且代码的某些部分有点模糊。
Here is what I need:
ClassA raises multiple events/signals
ClassB subscribes to those events (Multiple classes may subscribe)
这是我需要的:
ClassA 引发多个事件/信号
ClassB 订阅这些事件(多个类可以订阅)
In my project I have a lower-level message handler class that raises events to a business class that does some processing of those messages and notifies the UI (wxFrames). I need to know how these all might get wired up (what order, who calls who, etc).
在我的项目中,我有一个较低级别的消息处理程序类,它将事件引发到一个业务类,该业务类对这些消息进行一些处理并通知 UI (wxFrames)。我需要知道这些都是如何连接起来的(什么顺序,谁打电话给谁,等等)。
回答by MattyT
The code below is a minimal working example of what you requested. ClassA
emits two signals; SigA
sends (and accepts) no parameters, SigB
sends an int
. ClassB
has two functions which will output to cout
when each function is called. In the example there is one instance of ClassA
(a
) and two of ClassB
(b
and b2
). main
is used to connect and fire the signals. It's worth noting that ClassA
and ClassB
know nothing of each other (ie they're not compile-time bound).
下面的代码是您请求的最小工作示例。 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);
}
The output:
输出:
Foo Bar: 4 Bar: 4
For brevity I've taken some shortcuts that you wouldn't normally use in production code (in particular access control is lax and you'd normally 'hide' your signal registration behind a function like in KeithB's example).
为简洁起见,我采用了一些您通常不会在生产代码中使用的快捷方式(特别是访问控制松懈,您通常会将您的信号注册“隐藏”在像 KeithB 示例中的函数后面)。
It seems that most of the difficulty in boost::signal
is in getting used to using boost::bind
. It isa bit mind-bending at first! For a trickier example you could also use bind
to hook up ClassA::SigA
with ClassB::PrintInt
even though SigA
does notemit an int
:
似乎大部分困难在于boost::signal
习惯使用boost::bind
. 这是一个有点令人费解的第一!对于一个更为复杂的例子,你也可以使用bind
挂钩ClassA::SigA
与ClassB::PrintInt
即使SigA
没有没有发出int
:
a.SigA.connect(bind(&ClassB::PrintInt, &b, 10));
Hope that helps!
希望有帮助!
回答by KeithB
Here is an example from our codebase. Its been simplified, so I don't guarentee that it will compile, but it should be close. Sublocation is your class A, and Slot1 is your class B. We have a number of slots like this, each one which subscribes to a different subset of signals. The advantages to using this scheme are that Sublocation doesn't know anything about any of the slots, and the slots don't need to be part of any inheritance hierarchy, and only need implement functionality for the slots that they care about. We use this to add custom functionality into our system with a very simple interface.
这是我们代码库中的一个示例。它被简化了,所以我不保证它会编译,但它应该是接近的。Sublocation 是您的 A 类,Slot1 是您的 B 类。我们有许多这样的槽,每个槽都订阅不同的信号子集。使用这种方案的优点是 Sublocation 不知道任何关于任何插槽的信息,并且插槽不需要成为任何继承层次结构的一部分,只需要为他们关心的插槽实现功能。我们使用它通过一个非常简单的界面将自定义功能添加到我们的系统中。
Sublocation.h
子位置.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;
};
Sublocation.C
子位置.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);
// ...
}
Slot1.h
插槽1.h
class Slot1
{
public:
Slot1(const Sublocation& subloc);
void onContact(Time t1, Time t2);
void onEndOfSim();
private:
const Sublocation& fSubloc;
};
Slot1.C
插槽1.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)
{
// ...
}
回答by éric Malenfant
Did you look at boost/libs/signals/example?
回答by Vihaan Verma
Boost like QT provides its own implementation of signals and slots. Following are some example of its implementation.
像 QT 一样的 Boost 提供了自己的信号和插槽实现。以下是其实现的一些示例。
Signal and Slot connection for namespace
命名空间的信号和槽连接
Consider a namespace called GStreamer
考虑一个名为 GStreamer 的命名空间
namespace GStremer
{
void init()
{
....
}
}
Here is how to create and trigger the signal
下面是如何创建和触发信号
#include<boost/signal.hpp>
...
boost::signal<void ()> sigInit;
sigInit.connect(GStreamer::init);
sigInit(); //trigger the signal
Signal and Slot connection for a Class
类的信号和插槽连接
Consider a Class called GSTAdaptor with function called func1 and func2 with following signature
考虑一个名为 GSTAdaptor 的类,其函数名为 func1 和 func2,其签名如下
void GSTAdaptor::func1()
{
...
}
void GSTAdaptor::func2(int x)
{
...
}
Here is how to create and trigger the signal
下面是如何创建和触发信号
#include<boost/signal.hpp>
#include<boost/bind.hpp>
...
GSTAdaptor g;
boost::signal<void ()> sigFunc1;
boost::signal<void (int)> sigFunc2;
sigFunc1.connect(boost::bind(&GSTAdaptor::func1, &g);
sigFunc2.connect(boost::bind(&GSTAdaptor::func2, &g, _1));
sigFunc1();//trigger the signal
sigFunc2(6);//trigger the signal
回答by psalong
When compiling MattyT's example with newer boost (f.e. 1.61) then it gives a warning
当使用较新的 boost (fe 1.61) 编译 MattyT 的示例时,它会发出警告
error: #warning "Boost.Signals is no longer being maintained and is now deprecated. Please switch to Boost.Signals2. To disable this warning message, define BOOST_SIGNALS_NO_DEPRECATION_WARNING."
So either you define BOOST_SIGNALS_NO_DEPRECATION_WARNING to suppress the warning or you could easily switch to boost.signal2 by changing the example accordingly:
因此,要么您定义 BOOST_SIGNALS_NO_DEPRECATION_WARNING 来抑制警告,要么您可以通过相应地更改示例轻松切换到 boost.signal2:
#include <boost/signals2.hpp>
#include <boost/bind.hpp>
#include <iostream>
using namespace boost::signals2;
using namespace std;