2017-09-22 120 views
2

我从boost :: signals2中断开一个插槽(这是一个类方法)时,我没有看到我期待的行为。我的术语很可能是关闭的,所以我将提供一个最低工作示例(MWE),以展示我所看到的和我期望的内容。简短的版本是我断开了信号,但它停留在那里。如果我使用独立函数做到这一点,那么所有的工作都很好,当我使用一个我遇到这种行为的类方法时。如何使用仿函数将boost信号2与类的方法断开连接?

任何帮助将不胜感激!

>> tree

. 
├── main.cpp 
└── SConstruct 

0 directories, 2 files 

>> cat SConstruct

Program('main.cpp') 

>> cat main.cpp

#include <boost/signals2.hpp> 
#include <iostream> 
struct foo { 
    void bar(int n) { 
     std::cout << "Called foo::bar with " << n << std::endl; 
    } 
}; 
typedef boost::function<void(int)> Signal_f; 
int main() { 

    foo f; 
    boost::signals2::signal< void(int) > my_signal; 
    Signal_f functor = boost::bind(&foo::bar, f, _1); 
    std::cout << "Created signal, and it has " 
       << my_signal.num_slots() << " subscribers." << std::endl; 
    my_signal.connect(functor); 
    std::cout << "Subscribed to signal, and it has " 
       << my_signal.num_slots() << " subsciber." << std::endl; 
    my_signal(1); 
    my_signal.disconnect(&functor); 
    std::cout << "Un-Subscribed to signal, but it still has " 
       << my_signal.num_slots() 
       << " subsciber, and it should not have any now." << std::endl; 
    my_signal(2); 
    return 0; 
} 

>> scons

scons: Reading SConscript files ... 
scons: done reading SConscript files. 
scons: Building targets ... 
g++ -o main.o -c main.cpp 
g++ -o main main.o 
scons: done building targets. 

>> ./main

Created signal, and it has 0 subscribers. 
Subscribed to signal, and it has 1 subsciber. 
Called foo::bar with 1 
Un-Subscribed to signal, but it still has 1 subsciber, and it should not have any now. 
Called foo::bar with 2 

回答

3

使用scoped_connection重新实现:

#include <boost/signals2.hpp> 
#include <iostream> 
struct foo { 
    void bar(int n) { 
     std::cout << "Called foo::bar with " << n << std::endl; 
    } 
}; 



typedef boost::function<void(int)> Signal_f; 
int main() { 

    using boost::signals2::scoped_connection; 

    foo f; 
    boost::signals2::signal< void(int) > my_signal; 
    Signal_f functor = boost::bind(&foo::bar, f, _1); 
    std::cout << "Created signal, and it has " 
       << my_signal.num_slots() << " subscribers." << std::endl; 

    // the scoped_connection object is RAII 
    auto con = scoped_connection(my_signal.connect(functor)); 

    std::cout << "Subscribed to signal, and it has " 
       << my_signal.num_slots() << " subsciber." << std::endl; 
    my_signal(1); 

    // disconnect the connection object, not the signal 
    con.disconnect(); 
    std::cout << "Un-Subscribed to signal, and it now has " 
       << my_signal.num_slots() 
       << " subscibers." << std::endl; 
    my_signal(2); 
    return 0; 
} 

预期输出:

Created signal, and it has 0 subscribers. 
Subscribed to signal, and it has 1 subsciber. 
Called foo::bar with 1 
Un-Subscribed to signal, and it still has 0 subscibers. 
+0

我喜欢的作用域连接的scoped_connection,但我希望不必在我的完整实施中管理另一个对象。仿函数对象已经被创建,并且将它理想地用于断开连接。如果没有其他人可以提供关于如何使用仿函数来断开连接的指导,我会接受这个答案,因为“你不能那样做,而是这样做。” –

+0

@ KennethE.Bellock还有另外一个选项 - signals2为您提供了使用'connect_extended'的机会,这会导致对连接的引用传递给插槽处理程序。 http://www.boost.org/doc/libs/1_61_0/libs/signals2/example/extended_slot.cpp –

1

我使用boost :: signals2 :: connect方法返回连接对象,从boost :: signal2 :: signal断开连接。

+0

我更喜欢自动处理的东西 – sehe