linux 事件处理函数,事件处理(下) - Boost学习系列_Linux编程_Linux公社-Linux系统门户网站...

合成器是一个重载了 operator()() 操作符的类。这个操作符会被自动调用,传入两个迭代器,指向某个特定信号的所有返回值。以上例子使用了标准 C++ 算法 std::min_element() 来确定并返回最小的值。

不幸的是,我们不可能把象 std::min_element() 这样的一个算法直接传给 boost::signal 作为一个模板参数。 boost::signal 要求这个合成器定义一个名为 result_type 的类型,用于说明 operator()() 操作符返回值的类型。由于在标准 C++ 算法中缺少这个类型,所以在编译时会产生一个相应的错误。

除了对返回值进行分析以外,合成器也可以保存它们。

#include 

#include 

#include 

#include 

intfunc1()

{

return1;

}

intfunc2()

{

return2;

}

template

structmin_element

{

typedefT result_type;

template

T operator()(InputIterator first, InputIterator last)const

{

returnT(first, last);

}

};

intmain()

{

boost::signal > > s;

s.connect(func1);

s.connect(func2);

std::vector v = s();

std::cout <

}

这个例子把所有返回值保存在一个 vector 中,再由 s() 返回。

三、连接 Connections

函数可以通过由 boost::signal 所提供的 connect() 和 disconnect() 方法的帮助来进行管理。 由于 connect() 会返回一个类型为 boost::signals::connection 的值,它们可以通过其它方法来管理。

#include 

#include 

voidfunc()

{

std::cout <

}

intmain()

{

boost::signal s;

boost::signals::connection c = s.connect(func);

s();

c.disconnect();

}

boost::signal的disconnect()方法需要传入一个函数指针,而直接调用 boost::signals::connection 对象上的 disconnect() 方法则略去该参数。

除了 disconnect() 方法之外,boost::signals::connection 还提供了其它方法,如 block() 和 unblock()。

#include 

#include 

voidfunc()

{

std::cout <

}

intmain()

{

boost::signal s;

boost::signals::connection c = s.connect(func);

c.block();

s();

c.unblock();

s();

}

以上程序只会执行一次 func()。 虽然信号 s 被触发了两次,但是在第一次触发时 func() 不会被调用,因为连接 c 实际上已经被 block() 调用所阻塞。 由于在第二次触发之前调用了 unblock(),所以之后 func() 被正确地执行。

除了boost::signals::connection 以外,还有一个名为 boost::signals::scoped_connection 的类,它会在析构时自动释放连接。

#include 

#include 

voidfunc()

{

std::cout <

}

intmain()

{

boost::signal s;

{

boost::signals::scoped_connection c = s.connect(func);

}

s();

}

因为连接对象 c 在信号触发之前被销毁,所以 func() 不会被调用。

boost::signals::scoped_connection 实际上是派生自 boost::signals::connection 的,所以它提供了相同的方法。它们之间的区别仅在于,在析构 boost::signals::scoped_connection 时,连接会自动释放。

虽然 boost::signals::scoped_connection 的确令自动释放连接更为容易,但是该类型的对象仍需要管理。如果在其它情形下连接也可以被自动释放,而且不需要管理这些对象的话,就更好了。

#include 

#include 

#include 

#include 

classworld

{

public:

voidhello()const

{

std::cout <

}

};

intmain()

{

boost::signal s;

{

std::auto_ptr w(newworld());

s.connect(boost::bind(&world::hello, w.get()));

}

std::cout <

s();

}

以上程序使用 Boost.Bind 将一个对象的方法关联至一个信号。 在信号触发之前,这个对象就被销毁了,这会产生问题。 我们不传递实际的对象 w,而只传递一个指针给 boost::bind()。 在 s() 被实际调用的时候,该指针所引向的对象已不再存在。

可以如下修改这个程序,使得一旦对象 w 被销毁,连接就会自动释放。

#include 

#include 

#include 

#include 

classworld :

publicboost::signals::trackable

{

public:

voidhello()const

{

std::cout <

}

};

intmain()

{

boost::signal s;

{

std::auto_ptr w(newworld());

s.connect(boost::bind(&world::hello, w.get()));

}

std::cout <

s();

}

如果现在再执行,num_slots()会返回0以确保不会试图调用已销毁对象之上的方法。仅需的修改是让world类继承自boost::signals::trackable。当使用对象的指针而不是对象的副本来关联函数至信号时,boost::signals::trackable可以显著简化连接的管理。

四、练习

编写一个程序,定义一个名为 button 的类,表示GUI中的一个可点击按钮。 为该类加入两个方法 add_handler() 和 remove_handler(),它们均要求一个函数名作为参数。 如果 click() 方法被调用,已登记的函数将被按顺序执行。

如下测试你的代码,创建一个 button 类的实例,从事件处理器内部向标准输出流写出一个信息。 调用 click() 函数模拟用鼠标点击该按钮。

五、解答

实在搞不懂这个Boost库了,我试了1_33、1_42、1_47三个版本,提示三种奇怪的头文件错误,开始时怀疑是我的老编译器VC6.0的问题,后来在linux下换用开源的Eclipse,居然也一样报错,无语,继续寻找问题,下面的代码是自己写的,为验证,待此问题解决后我会验证并修改错误。

#include 

#include 

#include 

#include 

/*使用该方法可以再结束后自动释放连接并销毁对象,最简洁*/

classbutton:publicboost::signals::trackable

{

public:

button(){}

voidadd_handler()

{

std::cout<

}

voidremove_handler()

{

std::cout<

}

};

intmain(intargc,char*argv[])

{

boost::signal click;

std::auto_ptr but(newbutton());

click.connect(boost::bind(&button::add_handler,but.get()));

click.connect(boost::bind(&button::remove_handler,but.get()));

click();

return0;

}0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值