C 语言

关注公众号 jb51net

关闭
首页 > 软件编程 > C 语言 > Qt C++中connect写法

关于Qt C++中connect的几种写法代码示例

作者:Winrich

这篇文章介绍了Qt中connect函数的不同编写方式,包括传统的槽函数写法、使用函数指针的写法、Lambda表达式以及使用QOverload选择重载信号的写法,每种写法都有其特点和适用场景,程序员应根据具体需求选择最合适的方式,需要的朋友可以参考下

前言

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

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

1. 传统的槽函数写法

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

class MainWindow : public QMainWindow {
  Q_OBJECT
 
public:
  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是槽函数的函数指针。编译器会在编译时检查这些指针是否匹配。这种写法的优点如下:

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("请输入合法的半径!");
  }
});

这种写法的优点如下:

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

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

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

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或函数指针来实现相同的功能,但这样做通常不太安全且容易出错。

具体优点:

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

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

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

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

总结

到此这篇关于关于Qt C++中connect的几种写法的文章就介绍到这了,更多相关Qt C++中connect写法内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文