关于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.xdnf.cn/news/19255.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

(二)PyTorch简要教学

文章目录 PyTorch教学一、训练一个神经网络二、用PyTorch是怎么去做的&#xff08;一&#xff09;Dataset & DataLoader&#xff08;二&#xff09;Tensors&#xff08;1&#xff09;Tensor是什么&#xff08;2&#xff09;怎么获得Tensor&#xff08;3&#xff09;Tensor相…

GRPC实现

1.首先下载对应编译插件&#xff0c;这里不再提供下载 2.编写proto文件 3.编写完成用命令生成go文件 protoc --go_out. --go-grpc_out. *.proto --go_out. 其中的. 是说你要编译的 .proto 文件目录为当前目录&#xff0c;按需修改 --go-grpc_out.&#xff0c;其中的. 是说你生…

Path does not exist: file:/D:/pythonProject/spark/main/datas/input/u.data

出现标题中的错误原因可能是&#xff1a; 1.文件路径书写错误&#xff1b; 2.文件本身不存在。 从图中可以看出&#xff0c;数据源文件是存在的&#xff0c;但是读取不到文件&#xff0c;说明代码中的文件路径写错了&#xff0c;从报错的结果可以看出&#xff0c;python在D:/…

Wallpaper壁纸制作学习记录01

导入图像 打开wallpaper软件&#xff0c;找到下方的播放列表&#xff0c;选择壁纸编辑器。 弹出下列界面&#xff0c;在创建壁纸处可以选择图片拖入。 在开始导入任何图像之前&#xff0c;请首先确保主背景图像表示实际屏幕分辨率。展示示例图像是 1920 x 1080&#xff0c;这…

【知识科普】统一身份认证CAS

什么是CAS 综合概述一、CAS概述二、CAS的组成与工作原理三、CAS的特性与支持四、CAS的应用场景 示例展示场景设定CAS认证过程 其他认证细节CAS认证过程的细节CAS认证过程的特性 参考文献 综合概述 统一身份认证CAS&#xff08;Central Authentication Service&#xff09;&…

计算机网络-MSTP工作原理

前面大致学习了MSTP基础概念与组成&#xff0c;今天来了解MSTP的工作原理。 一、MSTP拓扑计算&#xff1a; MSTP可以将整个二层网络划分为多个MST域&#xff0c;各个域之间通过计算生成CST&#xff0c;域内生成IST&#xff0c;CST和IST构成了整个交换设备网络的CIST。 域内还可…

面试题:Kafka(一)

1. Kafka如何保证消息不丢失 生产者发送消息到Brocker丢失 设置异步发送 消息重试 消息在Brocker中存储丢失 发送确认机制acks 消费者从Brocker接收消息丢失 Kafka 中的分区机制指的是将每个主题划分成多个分区&#xff08;Partition&#xff09;topic分区中消息只能由消费者…

odoo 创建应用

1、通过手脚架命令创建文件结构&#xff08;完全可以手动一个个文件/文件夹建&#xff09; odoo-bin scaffold <模块名> <模块放置路径> 在odoo根目录路径执行命令行&#xff1a;./odoo-bin scaffold my_library exte_addons 执行结果&#xff1a; 参考文章&…

十四、SpringMVC的执行流程

文章目录 1. SpringMVC常用组件2. DispatcherServlet初始化过程3. DispatcherServlet调用组件处理请求4. SpringMVC的执行流程 1. SpringMVC常用组件 2. DispatcherServlet初始化过程 3. DispatcherServlet调用组件处理请求 4. SpringMVC的执行流程

java基础概念30:常见API-System

一、System工具类的常用方法 System也是一个工具类&#xff0c;提供了一些与系统相关的方法。 计算机的时间原点:1970年1月1日0:0:0&#xff0c;我国在东八区&#xff0c;有8小时时差。 二、常用方法说明 2-1、System.exit()方法 该方法用于终止当前运行的Java虚拟机&#x…

基于AOA算术优化的KNN数据聚类算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 基于AOA算术优化的KNN数据聚类算法matlab仿真。通过AOA优化算法&#xff0c;搜索最优的几个特征数据&#xff0c;进行KNN聚类&#xff0c;同时对比不同个数特征下…

三维测量与建模笔记 - 点特征提取 - 4.3 Harris特征点

在3D重建应用中&#xff0c;很重要的一个场景是找到两幅图像中的同名特征点&#xff0c;这个过程需要对特征点进行提取和描述。 从上面描述可以看出&#xff0c;如果窗口处于颜色变化不明显或者没有变化的区域&#xff0c;E的值很小或为0&#xff1b;如果窗口处于边缘位置&…

labview使用报表工具从数据库导出数据

之前写了一篇labview从数据库导出数据到excel电子表格&#xff0c;但是是基于调用excel的activeX控件&#xff0c;有时候会有一些bug&#xff0c;就比如我工作机就无法显示方法&#xff0c;后面大哥指点才知道没有的原因是excel安装不完整。像我的工作机就没有这个选项。就需要…

WIFI-TTL透传模块说明书

WIFI-TTL透传模块说明书 V 1.0 2022-11-24 目录 1 简介... 4 2 模块参数... 4 3 接口定义... 5 4 设备配网... 6 5 AT指令... 11 6 恢复出厂... 12 7 设备配置... 13 7.1 配置界面说明... 13 7.2 TTL串口配置... 13 7.3 …

基于YOLOv8深度学习的智慧交通非机动车驾驶员头盔佩戴检测系统

随着智慧交通系统的快速发展和城市交通的日益复杂化&#xff0c;非机动车驾驶员的安全问题引起了广泛关注&#xff0c;尤其在发生交通事故时&#xff0c;佩戴头盔作为基础的保护措施&#xff0c;能够有效降低头部受伤的风险&#xff0c;保障非机动车驾驶员的生命安全。然而&…

Flutter踩坑:原生安卓页面向Flutter通信

Flutter踩坑&#xff1a;原生安卓页面向Flutter通信 前言 在 Flutter APP 的开发过程中&#xff0c;有时不仅需要使用 Flutter 提供的组件&#xff0c;还需要使用原生的组件。 例如在对接外部 SDK 时&#xff0c;如果自己重新实现 SDK 的逻辑&#xff0c;无疑是本末倒置。 前…

w043基于springboot的“衣依”服装销售平台的设计与实现

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0…

【计算机网络安全】湖北大学-mysql事务隔离性实验

参考数据库实验&#xff1a;并发控制实验&#xff08;MySQL&#xff09;-CSDN博客&#xff0c;大佬写的很好 实验环境 实验需要mysql环境&#xff0c;如果我们本机有mysql客户端&#xff0c;或者安装过phpstudy都可以直接用&#xff0c;Kali似乎也有。 本机启动phpstudy&…

UE5 猎户座漂浮小岛 08 构造脚本

视频教程 90后小陈老师的个人空间-90后小陈老师个人主页-哔哩哔哩视频 1.构造脚本 1.1 简介 类似构造函数代码创建多个效率高 1.2 添加静态网格体 1.3 散乱立方体 使用for循环生产10个立方体 随机位置生成10个散乱的立方体 1.4 整齐立方体 1.5 随机物体 1.6 样条实现曲度墙…

OpenHarmony-2.DeviceInfo适配

DeviceInfo适配说明 1.启动子系统设备信息说明 2.OHOS 2.1.OHOS 固定值参数适配 OHOS 固定值参数: const.ohos.version.security_patch const.ohos.releasetype const.ohos.apiversion const.ohos.fullname适配说明&#xff1a; OHOS 固定值参数由OHOS系统填充&#xff0…