首页 > 其他分享 >boost库之事件处理

boost库之事件处理

时间:2023-06-13 17:34:11浏览次数:49  
标签:事件处理 mySignal signal connect func include boost

一、概述

Boost.Signals所实现的模式被命名为"信号至插槽",它基于以下概念:当对应的信号被发出时,相关联的插槽即被执行,原则上,可以把"信号"和"插槽"分别替换为'事件'和'事件处理器',它提供了一个名为boost::signal的类,定义于boost/signal.hpp,实际上,这个头文件是唯一一个需要知道的,因为它会自动包含其他相关的头文件。在较新版本的boost库中,它定义于boost/signals2.hpp,并且提供了一个名为boost::signals2::signal的类。

二、Boost.Signals2的使用

Boost.Signals2是Boost库中的一个模块,用于实现信号和槽(signal/slot)机制。它提供了一种方便的方式来实现事件的发布和订阅,使不同的组件之间可以进行解耦的通信。

Boost.Signals2的核心是boost::signals2::signal类。下面是该类的简单介绍和使用示例:

  1. boost::signals2::signal类的基本特点:

    • 类似于发布-订阅模式,通过信号(signal)和槽(slot)进行通信。
    • 支持多个槽函数订阅同一个信号,当信号被触发时,所有订阅的槽函数都会被调用。
    • 可以选择不同的连接策略(connection policies)来管理连接和断开连接的行为。
    • 支持返回值的收集(collecting return values)和连接顺序的控制等高级功能。
  2. 使用Boost.Signals2的基本步骤:

    • 包含头文件:#include <boost/signals2.hpp>
    • 定义信号类型:boost::signals2::signal<Signature>,其中Signature是信号的函数签名,即槽函数的类型。
    • 定义槽函数:可以是全局函数、成员函数、lambda表达式等。
    • 连接信号和槽:使用signal.connect(slot)将槽函数与信号连接起来。
    • 触发信号:通过调用signal()来触发信号,会自动调用所有连接的槽函数。
#include <iostream>
#include <boost/signals2.hpp>

void func() {
    std::cout << "Hello World!" << std::endl;
}

int main() {
    boost::signals2::signal<void()> mySignal;
    mySignal.connect(&func);
    mySignal();

    return 0;
}

boost::signals2::signal实际上被实现为一个模板函数,具有被用作为事件处理器的函数的签名,该签名也是它的模板参数,在上述的例子中,只有签名为void()的函数可以被成功关联至信号mySignal。函数func()被connect()方法关联至信号s,由于func()符合所要求的void()签名,所以该关联成功建立,因为当信号mySignal被触发时,func()将被调用,信号是通过调用mySignal来触发的,就像普通的函数调用一样,这个函数的签名对应于作为模板参数传入的签名:因为void()不要求任何参数,所以括号内是空的,调用mySignal会引发一个触发器,进而执行相应的func()函数,之前用connect()关联的。

另外,Boost::Signals则提供了多对一的方式,如关联多个函数单个特定信号,示例如下:

#include <iostream>
#include <boost/signals2.hpp>

void func() {
    std::cout << "Hello";
}

void func1() {
    std::cout << " World!" << std::endl;
}

int main() {
    boost::signals2::signal<void()> mySignal;
    mySignal.connect(&func);
    mySignal.connect(&func1);
    mySignal();

    return 0;
}

boost::signal可以通过反复调用connect()方法把多个函数赋值给单个特定的信号,当该信号触发时,这些函数被按照之前用connect()进行关联时的顺序来执行。另外执行的顺序也可以通过connect()方法的另一个重载版本来明确指定,该重载版本要求以一个int类型的值作为额外的参数

#include <iostream>
#include <boost/signals2.hpp>

void func() {
    std::cout << " Hello" << std::endl;
}

void func1() {
    std::cout << "World";
}

int main() {
    boost::signals2::signal<void()> mySignal;
    mySignal.connect(1, &func);
    mySignal.connect(0, &func1);
    mySignal();

    return 0;
}

要释放某个函数与给定信号的关联,可以用disconnect()方法

#include <iostream>
#include <boost/signals2.hpp>

void func() {
    std::cout << "Hello";
}

void func1() {
    std::cout << " World!" << std::endl;
}

int main() {
    boost::signals2::signal<void()> mySignal;
    mySignal.connect(&func);
    mySignal.connect(&func1);
    mySignal.disconnect(&func1);
    mySignal();

    return 0;
}

上述例子仅输出Hello,因为与func2()的关联在触发信号之前已经被释放。

除了connect和disconnect()以外,boost::signal还提供了几个方法

#include <iostream>
#include <boost/signals2.hpp>

void func() {
    std::cout << "Hello";
}

void func1() {
    std::cout << " World!" << std::endl;
}

int main() {
    boost::signals2::signal<void()> mySignal;
    mySignal.connect(&func);
    mySignal.connect(&func1);
    std::cout << mySignal.num_slots() << std::endl;
    if (!mySignal.empty()) {
        mySignal();
    }
    return 0;
}

num_slots()返回已经关联函数的数量,如果没有函数被关联,则num_slots()返回0,在这种特定情况下,可以用empty()方法来代替,disconnect_all_slots()方法所做的实际上正是它的名字所表达的:释放所有已有的关联。

看完了函数如何被关联至信号,以及弄明白了信号触发时会发生什么事之后,还有一个问题,这些函数的返回值去了哪里?以下例子回答了这个问题:

#include <iostream>
#include <algorithm>
#include <boost/signals2.hpp>

int func() {
    return 10;
}

int func1() {
    return 20;
}

template <typename T>
struct min_element {
    typedef T result_type;

    template <typename InputIterator>
    T operator()(InputIterator first, InputIterator last) const {
        return T(first, last);
    }
};

int main() {
    boost::signals2::signal<int(), min_element<std::vector<int>>> mySignal;
    mySignal.connect(&func);
    mySignal.connect(&func1);
    std::vector<int> v = mySignal();
    std::cout << v.size() << std::endl;
    std::cout << *std::min_element(v.begin(), v.end()) << std::endl;

    return 0;
}

上述例子把所有返回值保存在一个vector中,再由mySignal()返回

三、连接Connections

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

#include <iostream>
#include <boost/signals2.hpp>

void func() {
    std::cout << "Hello World!" << std::endl;
}

int main() {
    boost::signals2::signal<void()> mySignal;
    boost::signals2::connection con = mySignal.connect(func);
    mySignal();
    con.disconnect();

    return 0;
}

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

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

#include <iostream>
#include <boost/signals2.hpp>

void func() {
    std::cout << "Hello World!" << std::endl;
}

int main() {
    boost::signals2::signal<void()> mySignal;
    {
        boost::signals2::scoped_connection con = mySignal.connect(func);
    }
    mySignal();

    return 0;
}

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

 

标签:事件处理,mySignal,signal,connect,func,include,boost
From: https://www.cnblogs.com/QingYiShouJiuRen/p/17478254.html

相关文章

  • react事件处理
     函数组件事件没有this  ......
  • Boost::asio范例分析 服务端
      main函数要求程序调用者传递3个参数:服务器IP地址,端口号和文档根目录.其中IP地址可以是IPv4或IPv6格式.接着创建server对象实例,将传递进来的IP地址,端口号,文档根目录作为server对象的构造函数参数传递到处理程序中.最后调用server的run成员函数启动服务端处理例程.   ......
  • #yyds干货盘点#【yyds干货盘点】5. Vue.js 事件处理
    学习目录:Vue.js简介Vue.js实例与数据绑定Vue.js计算属性和侦听器Vue.js条件渲染和列表渲染Vue.js事件处理Vue.js表单输入绑定Vue.js组件基础Vue.js组件通信Vue.js插槽Vue.js动态组件和异步组件Vue.js自定义指令Vue.js过渡和动画Vue.js混入Vue.js自定义事件和v-model......
  • boost.array 使用实例
    #include<iostream>//z包含array相关头文件。#include<boost/array.hpp>usingnamespacestd;usingnamespaceboost;//z仿函数,输出array各元素。classPrintInt{private:intsum;intcnt;public:PrintInt(intval):sum(......
  • boost库之智能指针
    一、boost::scoped_ptrboost::scoped_ptr是Boost库中的一个智能指针类,用于管理动态分配的对象,并确保在超出作用域时自动释放资源。boost::scoped_ptr提供了一种简单而安全的方式来管理对象的生命周期。它的行为类似于C++原始指针,但它负责在其生命周期结束时自动调用delete来释放......
  • Python信贷风控模型:Adaboost,XGBoost,SGD, SVC,随机森林, KNN预测信贷违约支付|附代码
    图形和统计输出。在此数据集中,我们必须预测信贷的违约支付,并找出哪些变量是违约支付的最强预测因子?以及不同人口统计学变量的类别,拖欠还款的概率如何变化有25个变量:ID: 每个客户的IDLIMIT_BAL: 金额SEX: 性别(1=男,2=女)4.教育程度:(1=研究生,2=本科,3=高中,4=其他,5=未知)5.婚......
  • 0007.有监督学习之集成学习(Adaboost算法)
    一、集成学习概述1.集成学习算法定义集成学习(Ensemblelearning)就是将若干个弱分类器通过一定的策略组合之后产生一个强分类器。弱分类器(weakClassifier)指的就是哪些分类准确率只比随机猜测略好一点的分类器,而强分类器(StrongClassifier)的分类准确率会高很多。这里的“强”&......
  • 条件渲染,列表渲染,双向数据绑定,事件处理,checkbox单选,
    条件渲染v-if,v-else-if,v-else:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>Title</title><scriptsrc="/js/vue.js"></script></head><......
  • Vue——属性指令、style和class、条件渲染、列表渲染、事件处理、数据双向绑定、过滤
    vm对象<body><divid="app"><h1>{{name}}</h1><button@click="handleClick">点我</button></div></body><script>//1写在data或method中的属性或方法,从vm中直接可以点出来//2method的函数中,如......
  • 常用的boosting算法
    boosting算法有许多种具体算法,包括但不限于adaboosting\GBDT\XGBoost。adaboosting原始数据集》某种算法拟合,会产生错误》根据上个模型预测结果,更新样本点权重(预测错误的结果权重增大)》再次使用模型进行预测》重复上述过程,继续重点训练错误的预测样本点。adabo......