返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C++Boost.Signals2信号/槽概念
  • 921
分享到

C++Boost.Signals2信号/槽概念

C++BoostSignals2C++Signals2信号 2022-12-08 20:12:53 921人浏览 薄情痞子
摘要

目录一、关于Boost.Signals2二、关于Signals库练习一、关于Boost.Signals2 Boost.Signals2 实现了信号/槽的概念。一个或多个函数(称为槽)

一、关于Boost.Signals2

Boost.Signals2 实现了信号/槽的概念。一个或多个函数(称为槽)与可以发出信号的对象相关联。每次发出信号时,都会调用链接的函数。

信号/槽概念在开发具有图形用户界面的应用程序时非常有用。可以对按钮进行建模,以便在用户单击它们时发出信号。它们可以支持指向许多函数的链接以处理用户输入。这样就可以灵活地处理事件。

std::function 也可用于事件处理。 std::function 和 Boost.Signals2 之间的一个重要区别是 Boost.Signals2 可以将多个事件处理程序与单个事件相关联。因此,Boost.Signals2更适合支持事件驱动开发,应该是任何需要处理事件的首选。

Boost.Signals2 继承了库 Boost.Signals,后者已被弃用且本书未讨论。

Table of Contents

Signals

Connections

Multithreading

二、关于Signals库

Boost.Signals2 提供类 boost::signals2::signal,可用于创建信号。此类在 boost/signals2/signal.hpp 中定义。或者,您可以使用头文件 boost/signals2.hpp,这是一个主头文件,定义了 Boost.Signals2 中可用的所有类和函数。

Boost.Signals2 定义了 boost::signals2::signal 和其他类,以及命名空间 boost::signals2 中的所有函数。

示例 67.1。 “你好世界!”使用 boost::signals2::signal

#include <boost/signals2.hpp>
#include <iOStream>
using namespace boost::signals2;
int main()
{
  signal<void()> s;
  s.connect([]{ std::cout << "Hello, world!\n"; });
  s();
}

boost::signals2::signal 是一个类模板,它期望将用作事件处理程序的函数的签名作为模板参数。在示例 67.1 中,只有签名为 void() 的函数才能与信号相关联。

lambda 函数通过 connect() 与信号 s 相关联。因为 lambda 函数符合所需的签名 void(),所以关联已成功建立。每当触发信号 s 时,都会调用 lambda 函数。

信号是通过像调用常规函数一样调用 s 来触发的。此函数的签名与作为模板参数传递的签名匹配。括号是空的,因为 void() 不需要任何参数。调用 s 会产生一个触发器,而该触发器又会执行之前与 connect() 相关联的 lambda 函数。

示例 67.1 也可以使用 std::function 实现,如示例 67.2 所示。

示例 67.2。 “你好世界!”使用 std::function

#include <functional>
#include <iostream>
int main()
{
  std::function<void()> f;
  f = []{ std::cout << "Hello, world!\n"; };
  f();
}

在示例 67.2 中,调用 f 时也会执行 lambda 函数。虽然 std::function 只能用于类似示例 67.2 的场景,但 Boost.Signals2 提供了更多种类。例如,它可以将多个函数与特定信号相关联(参见示例 67.3)。

示例 67.3。带有 boost::signals2::signal 的多个事件处理程序

#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
int main()
{
  signal<void()> s;
  s.connect([]{ std::cout << "Hello"; });
  s.connect([]{ std::cout << ", world!\n"; });
  s();
}

boost::signals2::signal 允许您通过重复调用 connect() 将多个函数分配给特定信号。每当触发信号时,函数都会按照它们与 connect() 关联的顺序执行。

顺序也可以在 connect() 的重载版本的帮助下明确定义,它需要一个 int 类型的值作为附加参数(示例 67.4)。

示例 67.4。具有明确顺序的事件处理程序

#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
int main()
{
  signal<void()> s;
  s.connect(1, []{ std::cout << ", world!\n"; });
  s.connect(0, []{ std::cout << "Hello"; });
  s();
}

与前面的示例一样,示例 67.4 显示 Hello, world!。

要从信号中释放关联函数,请调用 disconnect()。

示例 67.5。断开事件处理程序与 boost::signals2::signal 的连接

#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
void hello() { std::cout << "Hello"; }
void world() { std::cout << ", world!\n"; }
int main()
{
  signal<void()> s;
  s.connect(hello);
  s.connect(world);
  s.disconnect(world);
  s();
}

Example 67.5 

示例 67.5 仅打印 Hello,因为与 world() 的关联在信号被触发之前已释放。

除了 connect() 和 disconnect() 之外,boost::signals2::signal 还提供了几个成员函数(参见示例 67.6)。

示例 67.6。 boost::signals2::signal 的附加成员函数

#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
int main()
{
  signal<void()> s;
  s.connect([]{ std::cout << "Hello"; });
  s.connect([]{ std::cout << ", world!"; });
  std::cout << s.num_slots() << '\n';
  if (!s.empty())
    s();
  s.disconnect_all_slots();
}

num_slots() 返回关联函数的数量。如果没有函数关联,num_slots() 返回 0。empty() 告诉您事件处理程序是否已连接。而 disconnect_all_slots() 的作用正如它的名字所说:它释放所有现有的关联。

示例 67.7。处理事件处理程序的返回值

#include <boost/signals2.hpp>
#include <iostream>
using namespace boost::signals2;
int main()
{
  signal<int()> s;
  s.connect([]{ return 1; });
  s.connect([]{ return 2; });
  std::cout << *s() << '\n';
}

在示例 67.7 中,两个 lambda 函数与信号关联。第一个 lambda 函数返回 1,第二个返回 2。

示例 67.7 将 2 写入标准输出。 s 正确接受了两个返回值,但除了最后一个之外的所有返回值都被忽略了。默认情况下,只返回所有关联函数的最后一个返回值。

请注意,s() 不会直接返回上次调用的函数的结果。返回类型为 boost::optional 的对象,取消引用时返回数字 2。触发与任何函数无关的信号不会产生任何返回值。因此,在这种情况下,boost::optional 允许 Boost.Signals2 返回一个空对象。 boost::optional 在第 21 章中介绍。

可以自定义信号,以便相应地处理各个返回值。为此,必须将组合器作为第二个模板参数传递给 boost::signals2::signal。

示例 67.8。使用用户定义的组合器查找最小返回值

#include <boost/signals2.hpp>
#include <vector>
#include <alGorithm>
#include <iostream>
using namespace boost::signals2;
template <typename T>
struct min_element
{
  typedef T result_type;
  template <typename InputIterator>
  T operator()(InputIterator first, InputIterator last) const
  {
    std::vector<T> v(first, last);
    return *std::min_element(v.begin(), v.end());
  }
};
int main()
{
  signal<int(), min_element<int>> s;
  s.connect([]{ return 1; });
  s.connect([]{ return 2; });
  std::cout << s() << '\n';
}

组合器是一个具有重载的 operator() 的类。该运算符使用两个迭代器自动调用,这两个迭代器用于访问与特定信号关联的函数。当迭代器被取消引用时,函数被调用并且它们的返回值在组合器中变得可用。然后可以使用标准库中的常用算法,例如 std::min_element() 来计算并返回最小值(参见示例 67.8)。

boost::signals2::signal 使用 boost::signals2::optional_last_value 作为默认组合器。此组合器返回 boost::optional 类型的对象。用户可以定义一个具有任何类型返回值的组合器。例如,示例 67.8 中的组合器 min_element 返回作为模板参数传递给 min_element 的类型。

无法将诸如 std::min_element() 之类的算法作为模板参数直接传递给 boost::signals2::signal。 boost::signals2::signal 期望组合器定义一个名为 result_type 的类型,它表示 operator() 返回值的类型。由于这个类型没有被标准算法定义,所以编译器会报错。

请注意,不可能将迭代器 first 和 last 直接传递给 std::min_element() ,因为该算法需要前向迭代器,而组合器使用输入迭代器。这就是为什么在使用 std::min_element() 确定最小值之前使用向量存储所有返回值的原因。

示例 67.9 修改组合器以将所有返回值存储在容器中,而不是评估它们。它将所有返回值存储在一个向量中,然后由 s() 返回该向量。

示例 67.9。使用用户定义的组合器接收所有返回值

#include <boost/signals2.hpp>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace boost::signals2;
template <typename T>
struct return_all
{
  typedef T result_type;
  template <typename InputIterator>
  T operator()(InputIterator first, InputIterator last) const
  {
    return T(first, last);
  }
};
int main()
{
  signal<int(), return_all<std::vector<int>>> s;
  s.connect([]{ return 1; });
  s.connect([]{ return 2; });
  std::vector<int> v = s();
  std::cout << *std::min_element(v.begin(), v.end()) << '\n';
}

练习

创建一个带有课程按钮的程序。该类应代表图形用户界面中的按钮。添加成员函数 add_handler() 和 remove_handler() ,它们都希望传递一个函数。如果调用另一个名为 click() 的成员函数,则应依次调用已注册的处理程序。通过注册一个将消息写入标准输出的处理程序来实例化按钮并测试该类。调用 click() 来模拟鼠标点击按钮。

到此这篇关于c++ Boost.Signals2信号/槽概念的文章就介绍到这了,更多相关C++ Boost Signals2内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C++Boost.Signals2信号/槽概念

本文链接: https://lsjlt.com/news/174294.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C++Boost.Signals2信号/槽概念
    目录一、关于Boost.Signals2二、关于Signals库练习一、关于Boost.Signals2 Boost.Signals2 实现了信号/槽的概念。一个或多个函数(称为槽)...
    99+
    2022-12-08
    C++ Boost Signals2 C++ Signals2信号
  • 详解c++实现信号槽
    目录用c++实现信号槽机制(signal-slot)总结用c++实现信号槽机制(signal-slot) 信号槽机制的个人理解:信号槽是在两个c++类对象之间建立联系的通道,其中一...
    99+
    2024-04-02
  • redis分槽的概念是什么
    Redis分槽(Slot)是Redis集群中用于数据分片的概念。Redis将数据分片存储在多个节点上,每个节点负责管理一部分数据。为...
    99+
    2023-09-09
    redis
  • C#的概念是什么
    本文小编为大家详细介绍“C#的概念是什么”,内容详细,步骤清晰,细节处理妥当,希望这篇“C#的概念是什么”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。C#简介    &nb...
    99+
    2023-06-27
  • C++基础概念讲述
    目录1.C++相关网站推荐2.C++和C的关系3.C++特性说明3.1与底层硬件紧密结合3.2对象生命周期的精确控制3.3Zero-Overhead Abstraction首先,通过...
    99+
    2024-04-02
  • 深入理解Qt信号槽机制
    目录1. 信号和槽概述1.1 信号的本质1.2 槽的本质1.3 信号和槽的关系1. 信号和槽概述 信号槽是 Qt 框架引以为豪的机制之一。所谓信号槽,实际就是观察者模式(发布-订阅模...
    99+
    2024-04-02
  • C#中闭包概念讲解
    理解C#中的闭包 1、 闭包的含义 首先闭包并不是针对某一特定语言的概念,而是一个通用的概念。除了在各个支持函数式编程的语言中,我们会接触到它。一些不支持函数式编程的语言中也能支持闭...
    99+
    2024-04-02
  • C++基础概念是什么
    这篇文章主要讲解了“C++基础概念是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C++基础概念是什么”吧!首先,通过一张最新(2021.11)的编程语言排名图来了解常见的编程语言:从图...
    99+
    2023-06-22
  • C#概念指的是什么
    这篇文章给大家介绍C#概念指的是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。C#概念谈到C#入门我们首先来看看C#,它是是一种简洁、类型安全的面向对象的语言,开发人员可以使用它来构建在 .NET Framewor...
    99+
    2023-06-17
  • C# Lambda Expression概念是什么
    本篇内容主要讲解“C# Lambda Expression概念是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C# Lambda Expression概念是什么”吧!1.关于C# Lambd...
    99+
    2023-06-17
  • Qt开发实现跨窗口信号槽通信
    多窗口通信,如果是窗口类对象之间互相包含,则可以直接开放public接口调用,不过,很多情况下主窗口和子窗口之间要做到异步消息通信,就必须依赖到跨窗口的信号槽,以下是一个简单的示例。...
    99+
    2024-04-02
  • PyQt5信号与槽机制案例详解
    信号和槽机制是 QT 的核心机制,要精通 QT 编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要...
    99+
    2024-04-02
  • C++异常的概念是什么
    C++异常的概念是什么,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。运用编程语言进行程序开发时,都需要进行异常的处理,才能使我们的程序完善。在C++语言中,同样也有关于异常...
    99+
    2023-06-17
  • c++类和对象基本概念
    目录什么是类?什么是对象?类的定义创建对象成员访问(初始化)总结什么是类? 一系列事物的抽象,对于c++而言,万事万物都可以是类。 类包括:属性+行为 属性:事物特征->数据类...
    99+
    2024-04-02
  • c#中#region的概念是什么
    在C#中,#region 是用来定义一个折叠区域的标记,可以帮助开发人员组织和管理代码。通过使用 #region 标记,可以将一段代...
    99+
    2024-03-05
    c#
  • c++中null的概念是什么
    在C++中,通常使用nullptr关键字来表示空指针或空对象。nullptr是C++11引入的一种特殊类型的字面值,用于表示空指针。...
    99+
    2024-03-12
    c++
  • 拨号VPS主机的概念是什么
    拨号VPS主机是一种虚拟专用服务器(VPS),用户可以通过拨号连接来访问该服务器。与传统的VPS主机不同,拨号VPS主机不需要通过网...
    99+
    2024-04-23
    vps
  • Qt开发如何实现跨窗口信号槽通信
    这篇文章主要介绍“Qt开发如何实现跨窗口信号槽通信”,在日常操作中,相信很多人在Qt开发如何实现跨窗口信号槽通信问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Qt开发如何实现跨窗口信号槽通信”的疑惑有所帮助!...
    99+
    2023-06-22
  • qt中信号和槽的作用是什么
    在Qt中,信号和槽是一种用于对象之间通信的机制。信号和槽允许对象在特定事件发生时发送信号,其他对象可以连接到这些信号并在接收到信号时...
    99+
    2023-09-27
    qt
  • Qt信号与槽知识点总结归纳
    目录一.含义与使用(一).含义(二).connect使用(三).信号函数(四).槽函数二.示例总结一.含义与使用 (一).含义 信号与槽是qt中一种常用的通信手段。发送方发送信号,接...
    99+
    2022-12-28
    qt信号与槽机制 qt信号的定义 qt信号与槽函数
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作