QT 信号与槽中Qt::UniqueConnection与lambda结合使用遇到的问题

1、背景:
在使用信号与槽的时候,槽函数使用的是lambda表达式,但是第五个参数(连接类型)写的是Qt::UniqueConnection。例如:

connect(this, &Dialog::signal_test, this, [=](){
        qDebug()<<"coming";
    },Qt::UniqueConnection);

然后实际运行发现,此槽函数可以被绑定多次。
2、原因:
1)最直接的解释,可参考QT 关于connect的文档:

Note: Qt::UniqueConnections do not work for lambdas, non-member functions and functors; they only apply to connecting to member functions.

2)调试发现,槽函数为成员函数和lambda时,各自调用的内部函数不一样。
a)成员函数,例如:

connect(this,&Dialog::signal_test,this, &Dialog::TestSlot,Qt::UniqueConnection);

调用的是:
成员函数
b)lambda表达式,例如:

connect(this, &Dialog::signal_test, this, [=](){
        qDebug()<<"coming";
    },Qt::UniqueConnection);

调用的是:
lambda表达式
而关于QObject::connectImpl中,此函数的第四个参数:
connectImpl
在后续的QObjectPrivate::connectImpl中:

...
 if (type & Qt::UniqueConnection && slot && QObjectPrivate::get(s)->connections.loadRelaxed()) {
        QObjectPrivate::ConnectionData *connections = QObjectPrivate::get(s)->connections.loadRelaxed();
        if (connections->signalVectorCount() > signal_index) {
            const QObjectPrivate::Connection *c2 = connections->signalVector.loadRelaxed()->at(signal_index).first.loadRelaxed();

            while (c2) {
                if (c2->receiver.loadRelaxed() == receiver && c2->isSlotObject && c2->slotObj->compare(slot)) {
                    slotObj->destroyIfLastRef();
                    return QMetaObject::Connection();
                }
                c2 = c2->nextConnectionList.loadRelaxed();
            }
        }
        type = static_cast<Qt::ConnectionType>(type ^ Qt::UniqueConnection);
    }
...

会去判断slot。
所以成员函数会返回 “return QMetaObject::Connection();”,lambda会继续绑定成功。

3、解决方法:
1)将lambda表达式写成成员函数;
2)人为保障连接的唯一性,即要么在初始化的时候绑定,要么绑定前先调用disconnect。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用的代码片段显示了一个Qt信号的例子,其有一个重载的finished信号。引用的错误提示说明在连接信号时出现了问题。而引用提供了一个解决方法,使用lambda表达式连接信号。 在Qt信号是一种机制,用于在对象之间进行通信。可以通过连接一个信号与一个来实现这种通信。在连接信号时,需要确保信号的参数类型和数量匹配。 针对你的问题,如果你想连接一个重载的信号,你需要使用static_cast将信号的函数指针转换为特定的参数类型。引用的代码示例展示了如何连接一个重载的finished信号,并使用lambda表达式作为函数。 在这个例子,我们创建了一个QProcess对象,并将其连接到一个重载的finished信号lambda表达式被用作函数,当信号被触发时,lambda表达式的代码将被执行。 请注意,lambda表达式的参数类型和数量必须与信号的参数类型和数量相匹配。在这个例子,我们忽略了exitCode参数,只使用了int类型的参数。 希望这个解释能帮助你理解如何在Qt5连接信号,并使用lambda表达式作为函数。123 #### 引用[.reference_title] - *1* *2* *3* [Qt 5使用lambda表达式连接信号](https://blog.csdn.net/weixin_39568531/article/details/108870524)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值