关于Qt C++中connect的几种写法

目录

1. 传统的槽函数写法

2. 使用函数指针的connect写法(5.0)

3. Lambda表达式作为槽函数(C++11)

4.使用QOverload选择重载信号的写法


connect函数就像是编程世界里的“茴”字,千变万化,各有千秋。咱们程序员呢,就像是孔乙己那样,虽然有时候会觉得这些变化有些好笑,甚至有些令人头疼,但说到底,还不是得乖乖地学着、用着,毕竟这可是编程里的“必备技能”。connect的编写每个人都有自己的习惯,也有其特点,还是要深究一下的。

在Qt中,connect函数用于将信号(signal)与槽(slot)连接起来,以便在信号被发射时自动调用槽函数。Qt提供了几种不同的connect写法,以及定义槽函数的方式,它们各有特点和适用场景。

1. 传统的槽函数写法

在传统的Qt项目中,槽函数通常是在类的头文件中使用slots:关键字声明的特殊成员函数。例如:

class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots: // 使用slots关键字声明槽函数void onCalculateClicked();// ... 其他成员和槽函数 ...
};

然后在源文件中实现这个槽函数:

void MainWindow::onCalculateClicked() {// 槽函数的实现
}

使用这种写法时,conect函数通常这样调用:

connect(pbt, SIGNAL(clicked()), this, SLOT(onCalculateClicked()));

这里使用的是SIGNAL()SLOT()宏来将信号和槽转换为字符串形式的标识符。

2. 使用函数指针的connect写法(5.0)

在5.0及后续的Qt版本中,推荐使用函数指针的connect写法,因为它提供了更好的类型检查和编译时错误检测。这种写法不需要使用slots:关键字或SIGNAL()/SLOT()宏,而是直接使用函数指针。例如:

connect(pbt, &QPushButton::clicked, this, &MainWindow::onCalculateClicked);

在这种写法中,&QPushButton::clicked是信号clicked的函数指针,&MainWindow::onCalculateClicked是槽函数的函数指针。编译器会在编译时检查这些指针是否匹配。这种写法的优点如下:

  1. 类型安全
    函数指针的connect写法提供了编译时的类型检查。这意味着如果信号和槽的函数签名不匹配,或者指定的函数不存在,编译器会立即给出错误提示。这大大减少了运行时错误的可能性,因为所有的连接都是在编译时验证的。

  2. 易于阅读和维护
    使用函数指针使得代码更加直观和易于理解。你可以直接看到哪个信号被连接到了哪个槽,而不需要通过字符串来间接表示。这有助于代码的维护和调试,因为你可以更容易地跟踪信号和槽之间的连接关系。

  3. 自动处理函数重载
    当存在多个重载的信号或槽函数时,使用函数指针可以自动选择正确的重载版本。传统的SIGNAL()SLOT()宏在处理重载函数时可能会遇到问题,因为它们依赖于函数名的字符串表示,无法区分重载的函数。而函数指针则包含了函数的完整签名,因此可以准确地选择所需的函数。

  4. 提高性能
    虽然性能差异可能不是非常显著,但使用函数指针的connect写法可能比使用字符串的宏稍微快一些。这是因为函数指针可以直接在编译时解析和连接,而不需要在运行时进行字符串比较和查找。

  5. 与现代C++标准兼容
    随着C++标准的不断发展,使用函数指针的connect写法更符合现代C++的编程风格。它利用了C++11及更高版本中的特性,如lambda表达式和智能指针,使得Qt的代码可以与这些现代特性更好地集成。

  6. 减少宏的使用
    减少宏的使用可以降低代码的复杂性和潜在的错误。宏在C++中经常是导致难以调试的问题的源头,因为它们是在预处理阶段展开的,而不是在编译阶段进行类型检查的。使用函数指针可以避免这些问题。

3. Lambda表达式作为槽函数(C++11)

在C++11以后,除了传统的槽函数和函数指针,Qt还支持使用Lambda表达式作为槽函数。这种写法非常灵活,因为它允许你在connect调用中直接编写槽函数的代码,而不需要在类中定义额外的成员函数。例如:

connect(pbt, &QPushButton::clicked, this, [this]() {// Lambda表达式作为槽函数的实现bool isOK;double r = lEdit->text().toDouble(&isOK);if (isOK && r >= 0) {lab2->setText(QString::number(AreaCircal(r)));} else {lab2->setText("请输入合法的半径!");}
});

这种写法的优点如下:

  1. 捕获或引用捕获的方式来控制这些变量的生命周期和作用域。

  2. 灵活性和动态性
    Lambda表达式提供了一种灵活的方式来定义槽函数的行为。你可以在connect调用中直接编写Lambda表达式,而不需要事先在类中声明槽函数。这使得你可以根据需要在运行时动态地定义槽函数的行为。

  3. 减少代码量
    使用Lambda表达式作为槽函数可以减少需要编写的代码量。你不需要为每个槽函数都声明一个成员函数,这不仅可以减少代码量,还可以使代码更加紧凑和易于管理。

  4. 类型安全
    与传统的字符串宏相比,使用Lambda表达式作为槽函数提供了更好的类型安全。编译器会在编译时检查Lambda表达式的类型是否与信号的参数类型匹配,从而避免了运行时错误。

除了第一种传统写法外,现在较为流行的二、三种写法对比分析如下:

特性Lambda表达式函数指针
引入时间C++11C++早期版本、Qt5.0
定义方式匿名函数,直接在代码中定义需要显式声明和定义函数,然后通过函数指针指向该函数
语法简洁性简洁,直接在调用处定义相对繁琐,需要额外的函数声明和定义
类型推断支持,编译器可根据上下文推断类型不支持,需要显式指定函数返回类型和参数类型
捕获外部变量可以捕获外部作用域中的变量无法直接捕获外部变量,只能访问函数参数
执行环境在新的栈帧中执行,具有独立的调用环境和栈空间指向已存在的函数,不拥有独立的栈空间
灵活性适用于简单的、单行表达式的场合,易于在需要的时间和地点实现功能闭包适用于调用已经定义好的函数,支持动态绑定和回调函数
代码重用性通常用于一次性或短暂的函数定义,代码重用性较低可以通过函数指针在不同位置调用同一函数,代码重用性较高
类型安全性类型安全,编译器检查函数签名类型安全性较低,容易出现类型不匹配的问题
性能现代编译器优化后性能损失可忽略,但在某些情况下可能带来轻微开销通常性能开销较低,但间接调用可能带来一些额外开销
使用场景适用于需要定义简单匿名函数的场景,如STL算法中的排序和过滤适用于需要动态调用不同函数或实现回调函数的场景,如事件处理、插件系统等

上述三种方法的特点和区别总结:

  • 传统槽函数:易于阅读和维护,特别是在槽函数逻辑复杂或需要多次重用的情况下。但是,它们增加了类的复杂度,因为需要在头文件中声明槽函数。
  • 函数指针的connect:提供了更好的类型安全性,减少了运行时错误的可能性。它是现代Qt编程的推荐方式。
  • Lambda表达式:非常灵活,适用于简单的、一次性的槽函数逻辑。但是,如果Lambda表达式过于复杂,可能会降低代码的可读性。

4.使用QOverload选择重载信号的写法(Qt5.7)

使用QOverload选择重载信号的写法同样是在Qt5引入的,在Qt框架中具有显著的优点,并且适用于特定的场景。例如使用comboBox时,有时使用索引,有时使用字符串作为参数:
 

    QComboBox *comboBox = new QComboBox;QLabel *label = new QLabel;label->setText("初始文本");// 添加一些选项到组合框comboBox->addItem("选项 1");comboBox->addItem("选项 2");comboBox->addItem("选项 3");// 使用 QOverload 来连接重载的信号到不同的槽QObject::connect(comboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),[](int index){ qDebug() << "当前索引改变:" << index; });QObject::connect(comboBox, QOverload<const QString&>::of(&QComboBox::currentIndexChanged),[](const QString &text){ qDebug() << "当前文本改变:" << text; });

在这个例子中,currentIndexChanged信号被重载了两次:一次接受一个整型参数(表示当前选中项的索引),另一次接受一个字符串参数(表示当前选中项的文本)。我们使用QOverload模板类来指定我们想要连接的是哪一个重载版本的信号。然后,我们使用lambda表达式来定义当信号发出时执行的代码。QOverload是Qt 5.7及更高版本中引入的一个模板类,它用于在连接重载信号时提供类型安全。在Qt 5.7之前的版本中,您可能需要使用static_cast或函数指针来实现相同的功能,但这样做通常不太安全且容易出错。

具体优点:

  1. 类型安全
    • 使用QOverload可以确保在连接信号和槽时,信号和槽的参数类型完全匹配。这有助于在编译时捕获潜在的错误,提高代码的稳定性。
  2. 清晰明确
    • 通过显式地指定要连接的重载信号版本,代码更加清晰易懂。其他开发者可以一目了然地看到信号和槽之间的对应关系,减少误解和错误。
  3. 灵活性
    • QOverload允许开发者在信号存在多个重载版本的情况下,选择最适合当前需求的信号版本进行连接。这增加了代码的灵活性,使其能够适应不同的场景和需求。
  4. 避免歧义
    • 在没有QOverload之前,如果信号存在多个重载版本,开发者需要通过其他方式(如函数指针转换)来指定要连接的信号版本,这可能会引入歧义和错误。而QOverload提供了一种直接且明确的方式来避免这些问题。

这种写法用于当信号存在多个重载版本时,通过QOverload模板类明确指定要连接的是哪一个重载版本的信号。比如comboBox::currentIndexChanged信号可能有多个重载版本,而通过使用QOverload<int>或QOverload<const QString&>明确指定,然后进行处理。适应场景:

  1. 信号存在多个重载版本
    • 当类中的信号存在多个重载版本时,使用QOverload可以明确指定要连接的重载信号版本,从而避免连接错误或歧义。
  2. 需要类型安全的信号槽连接
    • 在对类型安全要求较高的项目中,使用QOverload可以确保信号和槽的参数类型完全匹配,减少运行时错误的可能性。
  3. 复杂的GUI应用程序
    • 在复杂的GUI应用程序中,信号和槽的连接可能变得非常复杂。使用QOverload可以使代码更加清晰易懂,方便维护和管理。
  4. 需要灵活处理不同参数类型的场景
    • 在某些场景下,可能需要根据不同的参数类型来处理信号。使用QOverload可以方便地选择不同参数类型的信号版本进行连接,从而满足这些需求。

写到这里,感觉有点与孔乙己说的茴字的几种写法行为相仿,这里Qt里的connect函数,简直就是编程界的“茴”字啊!孔乙己要是穿越到编程世界,看到connect的种种写法,怕是要笑得胡子都抖掉了,心里还得嘀咕:“这信号槽的connect,怎地也有如此多般变化,真是绝了!”

想象一下,咱们这connect函数,简直就是编程里的“百搭小能手”,既能跟老式的函数指针眉来眼去,又能跟新潮的Lambda表达式暗送秋波,还能跟那信号映射机制搞点小暧昧。这不,就像孔乙己研究“茴”字的几种写法一样,咱们程序员也得琢磨琢磨connect的几种姿势-_-||b

在选择哪种写法时,应根据具体的需求和代码风格来决定。对于复杂的槽函数逻辑,传统的槽函数可能更合适;对于简单的逻辑或临时的连接,Lambda表达式可能更方便;而函数指针的connect则通常是一个折中的选择,既安全又易于使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/474423.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

常见网络厂商设备默认用户名/密码大全

常见网络厂商的默认用户名/密码 01 思科 (Cisco) 设备类型&#xff1a;路由器、交换机、防火墙、无线控制器 默认用户名&#xff1a;cisco 默认密码&#xff1a;cisco 设备类型&#xff1a;网管型交换机 默认用户名&#xff1a;admin 默认密码&#xff1a;admin 02 华…

elasticsearch是如何实现master选举的?

大家好&#xff0c;我是锋哥。今天分享关于【elasticsearch是如何实现master选举的&#xff1f;】面试题。希望对大家有帮助&#xff1b; elasticsearch是如何实现master选举的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Elasticsearch 中&…

讯飞、阿里云、腾讯云:Android 语音合成服务对比选择

在 移动端 接入语音合成方面&#xff0c;讯飞和腾讯云等都是优秀的选择&#xff0c;但各有其特点和优势。咱们的需求是需要支持普通话/英语/法语三种语言&#xff0c;以下是对各个平台的详细比较&#xff1a; 一、讯飞语音合成介绍 与语音听写相反&#xff0c;语音合成是将一段…

说说软件工程中的“协程”

在软件工程中&#xff0c;协程&#xff08;coroutine&#xff09;是一种程序运行的方式&#xff0c;可以理解成“协作的线程”或“协作的函数”。以下是对协程的详细解释&#xff1a; 一、协程的基本概念 定义&#xff1a;协程是一组序列化的子过程&#xff0c;用户能像指挥家…

使用 JavaScript 制作 To-Do List

使用 JavaScript 制作 To-Do List 本文记录了使用 HTML、CSS 和 JavaScript 制作一个简单的 To-Do List 网页的全过程&#xff0c;包含功能描述、代码实现以及优化方向。 **&#x1f389;&#x1f389;&#x1f389;欢迎来到我的博客,我是一名自学了2年半前端的大一学生,熟悉的…

HarmonyOs鸿蒙开发实战(16)=>沉浸式效果第一种方案一窗口全屏布局方案

1.沉浸式效果的目的 开发应用沉浸式效果主要指通过调整状态栏、应用界面和导航条的显示效果来减少状态栏导航条等系统界面的突兀感&#xff0c;从而使用户获得最佳的UI体验。 2.窗口全屏布局方案介绍 调整布局系统为全屏布局&#xff0c;界面元素延伸到状态栏和导航条区域实现沉…

【HarmonyOS】鸿蒙系统在租房项目中的项目实战(一)

从今天开始&#xff0c;博主将开设一门新的专栏用来讲解市面上比较热门的技术 “鸿蒙开发”&#xff0c;对于刚接触这项技术的小伙伴在学习鸿蒙开发之前&#xff0c;有必要先了解一下鸿蒙&#xff0c;从你的角度来讲&#xff0c;你认为什么是鸿蒙呢&#xff1f;它出现的意义又是…

基于STM32的智能语音识别饮水机系统设计

功能描述 1、给饮水机设定称呼&#xff0c;喊出称呼&#xff0c;饮水机回答&#xff1a;我在 2、语音进行加热功能&#xff0c;说&#xff1a;请加热&#xff0c;加热片运行 3、饮水机水位检测&#xff0c;低于阈值播报“水量少&#xff0c;请换水” 4、检测饮水机水温&#xf…

Java 使用MyBatis-Plus数据操作关键字冲突报错You have an error in your SQL syntax问题

问题 这个报错是出现在Java Spring boot项目中&#xff0c;使用MyBatis-Plus通过创建的实体类对数据库的操作过程中&#xff0c;通过实体创建数据库表是没有问题的&#xff0c;而在接口调用服务类操作数据库的时候&#xff0c;会出现报错。报错详情如下&#xff1a; 服务请求异…

高效工具推荐:基于WebGPU的Whisper Web结合内网穿透远程使用指南

文章目录 前言1.本地部署Whisper Web1.1 安装git1.2 安装Node.js1.3 运行项目 2. Whisper Web使用介绍3. 安装Cpolar内网穿透4. 配置公网地址5. 公网访问测试6. 配置固定公网地址 前言 OpenAI开源的 Whisper 语音转文本模型效果都说还不错&#xff0c;今天就给大家推荐 GitHub…

力扣-Mysql-3322- 英超积分榜排名 III(中等)

一、题目来源 3322. 英超积分榜排名 III - 力扣&#xff08;LeetCode&#xff09; 二、数据表结构 表&#xff1a;SeasonStats --------------------------- | Column Name | Type | --------------------------- | season_id | int | | team_id …

20241116解决在WIN11和ubuntu20.04通过samba共享时出现局域网千兆带宽拉满的情况

20241116解决在WIN11和ubuntu20.04通过samba共享时出现局域网千兆带宽拉满的情况 2024/11/16 13:42 缘起&#xff1a;最近需要通过iperf3打流&#xff0c;因此在ubuntu20.04服务器上常开sudo nethogs监控流量。 但是发现一个异常&#xff0c;ubuntu20.04服务器上发送的流量过大…

Stable Diffusion最全提示词写法教程

基础书写规则 所有单词都是通过英文书写&#xff0c;单词之间通过, 分割&#xff0c;注意是英文逗号&#xff1b;提示词之间是可以已通过换行书写的&#xff0c;并不会有什么影响&#xff1b;单个提示词的权重是1 , 默认情况下&#xff0c;越往前&#xff0c;权重越大&#xf…

TON商城与Telegram App:生态融合与去中心化未来的精彩碰撞

随着区块链技术的快速发展&#xff0c;去中心化应用&#xff08;DApp&#xff09;逐渐成为了数字生态的重要组成部分。而Telegram作为全球领先的即时通讯应用&#xff0c;不仅仅满足于传统的社交功能&#xff0c;更在区块链领域大胆探索&#xff0c;推出了基于其去中心化网络的…

Altenergy电力系统 status_zigbee SQL注入漏洞复现(CVE-2024-11305)

0x01 产品描述&#xff1a; Altenergy‌是一家专注于微型逆变器控制软件的公司&#xff0c;Altenergy电力系统控制软件是Altenergy电力系统公司的一款微型逆变器控制软件。 0x02 漏洞描述&#xff1a; Altenergy电力系统 status_zigbee接口处存在SQL注入漏洞&#xff0c;未经身…

3D Streaming 在线互动展示系统:NVIDIA RTX 4090 加速实时渲染行业数字化转型

随着科技的飞速发展&#xff0c;实时渲染正逐步成为游戏与实时交互领域的重要驱动力。与离线渲染不同&#xff0c;实时渲染需要极高的计算性能&#xff0c;对硬件设备尤其是GPU的性能要求极高。随着 RTX 4090 显卡的问世&#xff0c;其强大的算力和创新技术&#xff0c;为实时渲…

【vmware+ubuntu16.04】vm虚拟机及镜像安装-tools安装包弹不出来问题

学习机器人这门课需要下载虚拟机&#xff0c;做一下记录 首先我下载的是vm虚拟机16&#xff0c; 下载版本可参考该文章课堂上我下载 的镜像是16.04&#xff0c;虚拟机安装教程和镜像添加可参考该博主 按照教程安装成功 安装tools&#xff0c;但是我的弹不出来那个压缩包&…

Figma中文网:UI设计师的新资源宝库

Figma作为在线UI设计工具的先驱&#xff0c;已经在全球范围内被广泛使用&#xff0c;尤其是在中国&#xff0c;它已成为众多设计师的首选。本文将揭秘国内顶尖设计师们与Figma搭配使用的神秘伙伴——即时设计资源广场&#xff0c;这个被称为Figma中文网的平台&#xff0c;究竟有…

小试牛刀-Anchor安装和基础测试

目录 一、编写目的 二、安装步骤 2.1 安装Rust 设置rustup镜像 安装Rust 2.2 安装node.js 2.3 安装Solana-CLI 2.4 安装Anchor CLI 三、Program测试 四、可能出现的问题 Welcome to Code Blocks blog 本篇文章主要介绍了 [Anchor安装和基础测试] 博主广交技术好友&…

【后端】版本控制

版本控制 1. 什么是版本控制&#xff1f; 版本控制&#xff08;Revision control&#xff09;是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史&#xff0c;方便查看更改历史记录&#xff0c;备份以便恢复以前的版本的软件工程技术。简单来说就是用于管理…