尽管这个库的名字乍一看好象有点误导,但实际上并不是如此。 Boost.Signals 所实现的模式被命名为 '信号至插槽' (signal to slot)。它基于下面概念:当相应的信号被发出时。相关联的插槽即被运行。
原则上,你能够把单词 '信号' 和 '插槽' 分别替换为 '事件' 和 '事件处理器'。 只是,因为信号能够在随意给定的时间发出。所以这一概念放弃了 '事件' 的名字。
因此。Boost.Signals 没有提供不论什么类似于 '事件' 的类。
相反,它提供了一个名为 boost::signal
的类,定义于boost/signal.hpp
. 实际上,这个头文件是唯一一个须要知道的,由于它会自己主动包括其他相关的头文件。
Boost.Signals 定义了其他一些类。位于 boost::signals 名字空间中。 因为boost::signal
是最常被用到的类,所以它是位于名字空间boost 中的。
void func() { std::cout<<"Hello World!"<<std::endl; } int main() { signals2::signal <void()> s; s.connect(func); s(); return 0; }
boost::signal
实际上被实现为一个模板函数。具有被用作为事件处理器的函数的签名,该签名也是它的模板參数。 在这个样例中。仅仅有签名为void ()
的函数能够被成功关联至信号s。
函数 func()
被通过 connect()
方法关联至信号s。 因为func()
符合所要求的
void ()
签名,所以该关联成功建立。因此当信号s 被触发时,func()
将被调用。
信号是通过调用 s 来触发的,就象普通的函数调用那样。 这个函数的签名相应于作为模板參数传入的签名:由于
void ()
不要求不论什么參数,所以括号内是空的。
调用 s 会引发一个触发器,进而运行对应的 func()
函数 - 之前用connect()
关联了的。
int func1() { std::cout<<"func1"<<std::endl; return 1; } int func2() { std::cout<<"func2"<<std::endl; return 2; } int main() { boost::signals2::signal<int ()> s; s.connect(func1); s.connect(func2); std::cout<<s()<<std::endl; return 0; }
编译后输出:
func1
func2
1
func1()
和 func2()
都具有int
类型的返回值。
s 将处理两个返回值,并将它们都写出至标准输出流。 那么,究竟会发生什么呢?
以上样例实际上会把 1
写出至标准输出流。 两个返回值都被 s 正确接收。但除了第一个值。其他值都会被忽略。 缺省情况下,全部被关联函数中。实际上仅仅有第一个返回值被返回。
signal模拟程序:
- class Buttion
- {
- public:
- void connect(void (*f)(int, int));
- void OnBtnClick();
- private:
- void (*fuc_)(int, int);
- };
- void Buttion::connect(void (*f)(int, int))
- {
- fuc_ = f;
- }
- void Buttion::OnBtnClick()
- {
- fuc_(10, 20);
- }
- void PrintCodeline(int x, int y)
- {
- cout<<"x:"<<x<<",y:"<<y<<endl;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- Buttion btn;
- btn.connect(&PrintCodeline);
- btn.OnBtnClick();
- getchar();
- return 0;
- }