Qt 之 connect 信号和槽函数的连接、总结记录、 一

环境:win10  +qt 5.15.2

问题记录:

第一种connect连接方式:使用SIGNAL和SLOT宏
.h文件
QTimer *timSend;// 定时发送-定时器
.cpp文件
    timSend = new QTimer(this);
    connect(timSend, SIGNAL(timeout()), this, SLOT(obo_send_msg()));

现象,无法连接到槽函数,在工程中我的obo_send_msg();是串口发送函数,在实际调试过程消息发不出。.h不变换成换成下面的connect的写法问题解决。

这里,SIGNAL(timeout()) 表示 timSend 对象发出的名为 timeout 的信号。SLOT(obo_send_msg()) 则指定了接收这个信号的槽函数 obo_send_msg(),它是在 this (通常是指当前对象)。

第二种connect连接方式:使用&类名::函数名

刚开始我是这样写的;    connect(timSend, &QTimer::timeout, this, &Widget::obo_send_msg());

报错:

error: lvalue required as unary '&' operand   错误:左值需要作为一元'&'操作数

Cannot take the address of an rvalue of type 'void' 不能接受“void”类型右值的地址。

QT初学者问题cannot take the address of an rvalue of type 'void'_编程语言-CSDN问答

参考这个回答将槽函数改成此代码:

connect(timSend, &QTimer::timeout, this, &Widget::obo_send_msg);

问题解决消息发出,-那也就是说明我的obo_send_msg函数本身是没有问题的,我也参考了同事的代码发现写法跟我是一样的,他的可以我的不行,那么一定有什么地方是我忽略了的?两种写法也存在区别?还有为什么省略了()就可以?下面一一解答:

总结:

1.第一种如果没有指定 SLOT(obo_send_msg()) 的参数列表(如 SLOT(())),可能会导致连接失败,尤其是在 obo_send_msg() 需要参数的情况下。第二种写法简化了无参槽函数的连接过程,如果 obo_send_msg() 是无参的,那么直接写 obo_send_msg 就可以了。

2.省略()其实这是一个简化的形式,当省略了括号时,Qt会假设你想要连接一个不带参数的槽函数。这意味着即使 obo_send_msg() 原型声明了参数,这里也会尝试匹配一个无参的版本。如果你的 obo_send_msg() 实际上不需要参数,那么这就会正常地将信号和槽连接起来。

3.第二种写法是QT5中加入的一种重载形式,指定信号和槽两个参数不再使用SIGNAL()和 SLOT()宏,并且槽函数不再必须是使用slots关键字声明的函数可以是任意能和信号关联的成员函数。要使一个成员函数可以和信号关联,那么这个函数的参数数目不能超过信号的参数数目,但是并不要求该函数拥有的参数类型和信号中对应的参数类型完全一致,只需要可以进行隐式转换即可。

看到这句话一下点醒了我,查看obo_send_msg();声明果然定义在了private:中没有定义在private slots:中。这里也告诉我我们槽函数一定要定义在槽里,不要像我一样犯低级错误。

找到了问题,那就来找两种槽连接的区别和优缺点。结论就不必说了在我声明错误的情况下 使用&类名::函数名的方式都能准确地连接到目标函数,可见其准确性。

在Qt中,当你试图使用connect()函数将信号(SIGNAL)与槽(SLOT)关联起来时,如果直接使用SLOT()语法(如this, SLOT(obo_send_msg())),并且信号不是来自QObject的基类(比如在这里的QTimer),那么可能会出现连接失败的情况。

QTimer::timeout是一个特定于QTimer的信号,而obo_send_msg是你自定义类中的槽函数。当使用第一种写法时,SIGNAL(timeout())期望的是一个从继承了QObject的类派生出来的对象发出的timeout信号。由于QTimer本身就具有这个信号,所以你应该直接引用它的信号名称加上括号表示方法,而不是用SLOT()

第二种写法connect(timSend, &QTimer::timeout, this, &Widget::obo_send_msg)则是正确的,因为它明确指定了信号的成员函数地址(&QTimer::timeout)和接收者的对象以及槽函数(&Widget::obo_send_msg)。这种形式无论信号是否来自QObject的基类,都能准确地连接到目标函数。

connect(timSend, &QTimer::timeout, this, &YourClass::obo_send_msg);

总结一下:其中YourClass是包含obo_send_msg槽函数的那个类名。如果你不确定信号是从哪个基类继承来的,通常直接使用这种方式连接会更保险。

以下为网友总结

1、不需要写参数更简便。

2、不需要槽函数的参数类型与信号对应的参数类型完全一致,只需要进行隐藏式转换。

3、可以在编译时进行检查,比如信号或槽函数的拼写错误、槽函数参数数量多于信号的参数数量等都能在编译时期发现,而不是运行时。

就如一些qt的书所言:建议在编写Qt5的代码时使用&类名::函数名的connect方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值