C++ 使用boost::signals2处理多个信号/插槽的连接/断开

C++ 使用boost::signals2处理多个信号/插槽的连接/断开,c++,boost,signals,boost-signals2,C++,Boost,Signals,Boost Signals2,我已经开始使用boost::signals2而不是我以前的signals代码。但是,我在管理多个连接时遇到问题。我的问题是: 我有很多类人的例子: class Person { public: void SetName (string new_name) { name = new_name; NameChange (name); } string name; boost::signals2::signal<Perso

我已经开始使用boost::signals2而不是我以前的signals代码。但是,我在管理多个连接时遇到问题。我的问题是:

我有很多类人的例子:

class Person {
public:
    void SetName (string new_name)
    {
        name = new_name;
        NameChange (name);
    }

    string name;
    boost::signals2::signal<Person*> NameChange;
};
班级人员{
公众:
void SetName(字符串new_name)
{
名称=新名称;
姓名变更(姓名);
}
字符串名;
boost::signals2::信号名称更改;
};
我还有一个人员浏览器,它必须监视所有可用人员的子集,以便进行更改。由于人们可以从该子集来来去去,我必须有一种方法来处理连接对象,我创建了一个类(ConnectionList)来处理该类:

class ConnectionList
{
public:
    virtual ~ConnectionList () // drops all connections in "list"
    void add (boost::signals2::connection& conn); // adds "conn" to "list"
private:
    std::vector<boost::signals2::connection> list;
};

class PeopleBrowser
{
public:
    void AddPerson (Person& p)
    {
        name_change_connections.add (p.NameChange.connect (...));
    }
private:
    ConnectionList name_change_connections;
};
类连接列表
{
公众:
virtual~ConnectionList()//删除“列表”中的所有连接
void add(boost::signals2::connection&conn);//将“conn”添加到“list”
私人:
std::向量表;
};
类PeopleBrowser
{
公众:
void AddPerson(Person&p)
{
name_change_connections.add(p.NameChange.connect(…);
}
私人:
连接列表名称\u更改\u连接;
};
这一切都很好,当删除PeopleBrowser时,连接会被删除,并且有一种添加新连接的好方法

但是,我们需要添加另一个方法RemovePerson,该方法必须删除与该Person实例的NameChange信号的连接

这就是我被困的地方。我想我可以让ConnectionList成为一个模板,并使用一个列表来保存一个包含对信号和连接的引用的结构,然后添加一个方法来删除该信号的所有连接

但这似乎是一个很常见的情况(至少在我的世界里,我在这个应用程序中有20个类需要这个功能),所以我认为一定有更好的方法来处理这个问题

至少,有没有办法从连接对象获取连接信号的引用

也许libsigc++可以更好地/以不同的方式处理这个问题?

那么:

class PeopleBrowser
{
public:
    void AddPerson (Person& p)
    {
        name_change_connections[&p] = p.NameChange.connect(...);
    }
    void RemovePerson(Person& p)
    {
         name_change_connections.erase(&p);
    }

private:
    std::map<Person*, boost::signals2::scoped_connection> name_change_connections;
};
类人物浏览器
{
公众:
void AddPerson(Person&p)
{
name_change_connections[&p]=p.NameChange.connect(…);
}
无效移除人员(人员和p)
{
名称\更改\连接。擦除(&p);
}
私人:
std::映射名称\u更改\u连接;
};

您可能还想看看。

我自己没有试过,但根据

什么时候可以断开连接?(中级)

发生以下任一情况时,信号/插槽断开:

  • 直接通过连接的
    disconnect
    方法,或通过信号的
    disconnect
    方法,或
    作用域连接的析构函数,显式断开连接
  • 插槽跟踪的对象将被销毁
  • 信号被破坏了
除非使用
作用域_连接
,否则信号和插槽之间的连接将保持有效,直到其中一个被破坏。据我所知,不需要将连接对象存储在向量中。只需像现在这样将信号连接到插槽

当观察到的对象超出范围时,它将自行删除连接


这是一个更简单的设计。

在从映射中删除信号/插槽关系之前,是否还需要添加一个
disconnect
方法调用,以便实际断开信号/插槽关系?或者这会自动发生(即,在
boost::signals2::connection
对象的析构函数中处理)?您应该使用scoped_connection。谢谢,我现在已经实现了它,只是scoped_connection没有复制构造函数,所以我仍然有我的ConnectionList类,它在销毁时断开并删除所有连接。当我完成一些测试后,我将更新我的问题。连接对象本身占用一些内存,即使断开连接。因此,如果信号被破坏,连接对象将设置为disconnected,但不会解除分配。当PeopleBrowser被销毁时,其所有连接对象都将被解除分配,但PeopleBrowser可能会长期存在(在本例中,是在整个进程的生命周期内)。信号并不总是被破坏的,可能是PersonBrowser不再关心那个特定的人,也不应该再收到来自它的任何信号。