You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Qt多线程Signal&Slot未定义引用报错求助(切换基类无效)

问题解决:Qt线程间通信编译错误及逻辑修正

编译错误原因及解决步骤

1. 残留旧代码导致的未定义引用

错误信息中出现mclass相关未定义,但你提供的代码均为tthread类,说明项目可能残留旧的mclass文件或构建缓存:

  • 删除项目的debug/release构建目录
  • 在Qt Creator中右键项目选择「运行qmake」
  • 重新编译项目

2. Qt元对象工具(MOC)未正确生成代码

继承QObject并使用Q_OBJECT宏的类,必须通过MOC生成元对象代码:

  • 确保.pro文件中包含所有源文件:
    SOURCES += main.cpp tthread.cpp
    HEADERS += tthread.h
    
  • 修改头文件后需重新运行qmake,触发MOC更新

线程逻辑修正

你的代码存在线程启动逻辑错误,且无限循环会导致线程卡死,以下是修正后的完整代码:

tthread.h

#ifndef TTHREAD_H
#define TTHREAD_H
#include <QThread>
#include <QObject>
#include <QDebug>

class tthread : public QObject
{
    Q_OBJECT
public:
    explicit tthread(QObject *parent = nullptr);
    void startWork(); // 重命名避免和QThread的start方法冲突

signals:
    void sec(int value);
    void minu(int value);

public slots:
    void minutee(int value);
    void hourr(int value);

private:
    void secondd(); // 改为私有方法,通过startWork触发执行
};

#endif // TTHREAD_H

tthread.cpp

#include "tthread.h"
#include <QThread>

tthread::tthread(QObject *parent) : QObject(parent)
{
}

void tthread::startWork()
{
    qDebug() << "线程启动" << QThread::currentThread();
    secondd();
}

void tthread::secondd()
{
    int counter = 0;
    int sign = 1;
    while(true)
    {
        counter++;
        qDebug() << "秒计数器: " << counter << QThread::currentThread();

        if(counter == 5)
        {
            emit sec(sign);
            counter = 0;
            qDebug() << "发送秒信号到分线程" << QThread::currentThread();
        }
        QThread::msleep(100); // 添加休眠,避免线程占用100%CPU
    }
}

void tthread::minutee(int value)
{
    int counter2 = 0;
    int sign2 = 1;
    while(true)
    {
        qDebug() << "收到秒信号值: " << value ;
        counter2++;
        qDebug() << "分计数器: " << counter2 ;

        if(counter2 == 5)
        {
            emit minu(sign2);
            counter2 = 0;
            qDebug() << "发送分信号到小时线程";
        }
        QThread::msleep(100);
    }
}

void tthread::hourr(int value)
{
    int counter3 = 0;
    while(true)
    {
        qDebug() << "收到分信号值: " << value ;
        counter3++;
        qDebug() << "小时计数器: " << counter3 ;

        if(counter3 == 5)
        {
            counter3 = 0;
            qDebug() << "小时计数器重置";
        }
        QThread::msleep(100);
    }
}

main.cpp

#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QObject>
#include "tthread.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QThread t1;
    QThread t2;
    QThread t3;

    tthread thread1;
    tthread thread2;
    tthread thread3;

    thread1.moveToThread(&t1);
    thread2.moveToThread(&t2);
    thread3.moveToThread(&t3);

    // 绑定线程启动信号到工作函数
    QObject::connect(&t1, &QThread::started, &thread1, &tthread::startWork);
    // 线程间信号槽连接
    QObject::connect(&thread1, &tthread::sec, &thread2, &tthread::minutee);
    QObject::connect(&thread2, &tthread::minu, &thread3, &tthread::hourr);

    // 启动QThread实例,而非自定义方法
    t1.start();
    t2.start();
    t3.start();

    return a.exec();
}

.pro文件(确保配置正确)

QT += core
QT -= gui

TARGET = triple
CONFIG += c++17
SOURCES += main.cpp \
           tthread.cpp

HEADERS += tthread.h

关键修正说明

  • 遵循Qt线程规范:调用QThread::start()启动线程,通过QThread::started信号触发工作逻辑
  • 在无限循环中添加休眠,避免线程占用全部CPU资源并阻塞事件循环
  • 重命名自定义启动方法,避免与QThread的start方法冲突
  • 确保所有源文件被正确添加到项目配置中,保证MOC工具正常生成元对象代码

内容的提问来源于stack exchange,提问作者if4k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 17:05:28