当前位置: 首页 > news >正文

Qt 子类重新实现父类的槽函数

在重写槽函数时发现没有被调用(后来发现重写错了类,应该是重写类a,结果写的类b,测试时,只测试到了a),于是写了测试代码验证。

#ifndef PARENTSLOT_H
#define PARENTSLOT_H#include <QObject>
#include <QDebug>
#include <QThread>
class parentSlot:public QObject
{Q_OBJECT
public:parentSlot(QObject*p = nullptr){
//        connect(this,&parentSlot::signalTest,this,&parentSlot::slotTest,Qt::QueuedConnection);
//        connect(this,&parentSlot::signalTest,this,&parentSlot::slotTest,Qt::BlockingQueuedConnection);connect(this,SIGNAL(signalTest()),this,SLOT(slotTest()));
//        connect(this,SIGNAL(signalTest()),this,SLOT(slotTest()),Qt::QueuedConnection);emit signalTest();
//        slotTest();}
signals:void signalTest();void signal2();
public slots:virtual void slotTest(){QThread::sleep(3);qDebug() << " this is parent slotTest ";
//        emit signal2();}
};
class childSlot:public parentSlot
{Q_OBJECT
public:childSlot(QObject*p = nullptr):parentSlot(p){connect(this,&childSlot::signal2,this,&childSlot::slotChildTest);
//        emit signalTest();}
public slots:void slotTest(){qDebug() << " this is child slotTest start";parentSlot::slotTest();qDebug() << " this is child slotTest end";emit signal2();}void slotChildTest(){qDebug() << " this is child slotChildTest ";}
};
#endif // PARENTSLOT_H

这里在父类中关联了信号槽,也触发了信号,结果就是只调用到了父类的槽函数实现。因为信号接受和发送者是在同一个线程中,关联信号默认是Qt::AutoConnection,立即调用槽函数。

如果改成connect(this,SIGNAL(signalTest()),this,SLOT(slotTest()),Qt::QueuedConnection);这样就可以调用子类实现,如果信号关联和触发都在基类中,则只有用Qt::QueuedConnection才能调用子类实现

如果信号signalTest是在子类构造中触发,则可以直接调用子类实现

如果信号在其他地方emit触发,也是可以直接调用子类实现

    parentSlot(QObject*p = nullptr)
{        connect(this,&parentSlot::signalTest,this,&parentSlot::slotTest,Qt::BlockingQueuedConnection);
qDebug() << QThread::currentThreadId() << " parentSlot," << QThread::currentThread();        emit signalTest();

}

在main.cpp里

    QThread thread;
qDebug() << "thread " << thread.thread();
qDebug() << "currentThread " << QThread::currentThread()->currentThreadId();

    childSlot t;
t.moveToThread(&thread);
thread.start();

qDebug() << "end";

结果报错 死锁了

thread  QThread(0xbfff90)
currentThread  0x7fc83a6f4740
0x7fc83a6f4740  parentSlot, QThread(0xbfff90)
Qt: Dead lock detected while activating a BlockingQueuedConnection: Sender is parentSlot(0x7fffdaad3160), receiver is parentSlot(0x7fffdaad3160)

这里childSlot t;在主线程里构造,信号也是在构造函数中触发的,但实际确是认定信号是在子线程里触发,槽函数也是在子线程里,用了Qt::BlockingQueuedConnection,信号发起的线程要阻塞等槽的执行结束,就死锁了

    parentSlot(QObject*p = nullptr)
{  

//        connect(this,SIGNAL(signalTest()),this,SLOT(slotTest()));
connect(this,SIGNAL(signalTest()),this,SLOT(slotTest()),Qt::QueuedConnection);
qDebug() << QThread::currentThreadId() << " parentSlot," << QThread::currentThread();
}

main.cpp

    QThread thread;
qDebug() << "thread " << thread.thread();
qDebug() << "currentThread " << QThread::currentThread()->currentThreadId();

    childSlot t;
t.moveToThread(&thread);
thread.start();
QMetaObject::invokeMethod(&t, "slotTest", Qt::BlockingQueuedConnection); // 主线程调用了子线程里的槽函数,且阻塞等待槽函数执行结束才执行下面语句
qDebug() << "end";

结果是

thread  QThread(0x1078f90)
currentThread  0x7f2a9f1cd740
0x7f2a9f1cd740  parentSlot, QThread(0x1078f90)
this is child slotTest start
0x7f2a9a5c2700 , QThread(0x7ffc4d70c9c0)
this is parent slotTest 
this is child slotTest end
this is child slotChildTest 
end

如果QMetaObject::invokeMethod(&t, "slotTest", Qt::QueuedConnection);

则结果就是主线程调用了子线程里的槽函数,且继续执行下面语句,槽函数则在子线程里待事件循环空闲得以调用

thread  QThread(0x2603f90)
currentThread  0x7f43b5aac740
0x7f43b5aac740  parentSlot, QThread(0x2603f90)
end
this is child slotTest start
0x7f43b0ea1700 , QThread(0x7ffcbc114600)
this is parent slotTest 
this is child slotTest end
this is child slotChildTest 

Qt::AutoConnection 信号发起者和信号接受者在同一个线程就是Qt::DirectConnection立即调用,不在一个线程就是Qt::QueuedConnection,待接受者的线程事件循环空闲调用

Qt::DirectConnection 信号的发起者线程里立即调用

Qt::QueuedConnection 待接受者的线程事件循环空闲调用

Qt::BlockingQueuedConnection 信号发起的线程会阻塞等待槽函数执行完才能继续,所以得是不同的线程才行,不然就会死锁

Qt::UniqueConnection 与上面的用 | 结合使用,确保不再重复连接

http://www.dtcms.com/a/319286.html

相关文章:

  • 「iOS」————持久化
  • 【0基础3ds Max】菜单栏介绍
  • 【分享】我国八大沙漠空间矢量范围
  • Bonree ONE发布直通车 | 可观测平台如何深度应用LLM技术
  • 如何科学选择光伏运维系统?
  • docker安装半本地化安装方法
  • Shuffle SOAR使用学习经验
  • FreeRTOS2
  • 4G/5G无线电单元系统
  • 水下管道巡检机器人cad【10张】三维图+设计说明书
  • ai短视频与真人短视频哪个更好?
  • Docker容器部署harbor-小白级教学
  • Aurora MySQL 8.0 性能分析账号创建完整指南
  • ego-planner代码个人阅读笔记
  • 智慧物流分拣效率↑40%:陌讯多模态融合算法实战解析
  • Spring AI Alibaba 项目接入阿里云百炼平台大模型
  • leetcode-hot-100 (技巧)
  • STM32 HAL库外设编程学习笔记
  • SpringBoot中的单例注入方式
  • 上位机知识篇---AT指令
  • 「日拱一码」045 机器学习-因果发现算法
  • C 语言第 17 天学习笔记:从二级指针到内存布局的进阶指南
  • 力控汽车零部件冲压MES系统方案
  • 2025最新国内服务器可用docker源仓库地址大全(2025年8月更新) · DockerHub镜像加速全面指南
  • STM32学习笔记4-OLED外部中断和中断系统
  • nlp-句法分析
  • 虚幻GAS底层原理解剖八 (自定义子类)
  • nohup 学习笔记
  • AWS RDS自定义终端节点深度分析工具:Python脚本详解
  • PyTorch 核心三件套:Tensor、Module、Autograd