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

绕过Qt信号机制实现类间信号转发的代码错误排查

Qt自定义信号转发实现失效问题排查

你的代码存在5处明确错误,按影响优先级排序:

  • 核心逻辑错位:MyTimer本身继承自QTimer,你却在构造函数中额外new了一个内部QTimer* m_timer成员,只给这个内部定时器绑定了timeout信号。但后续Game中调用的配置、启动方法都是作用在MyTimer父类QTimer自身的实例上——等于你启动的是一个完全没绑定处理逻辑的外层定时器,真正绑了信号的内部m_timer从来没被配置、没被启动,自然不会触发回调。
  • API拼写错误:QTimer设置定时间隔的接口是驼峰命名的setInterval()(Interval首字母大写),你写的全小写setinterval不符合Qt API定义,编译阶段就会报找不到成员方法的错误。
  • 元对象宏缺失:所有继承QObject的类都必须在类定义开头加Q_OBJECT宏,否则Qt的MOC工具不会生成元对象代码,信号槽连接会在运行时失效。你的MyTimer类漏了这个宏。
  • 内存管理风险:你给内部new的m_timer传入了this作为父对象,Qt对象树会在MyTimer销毁时自动回收该子对象,你在析构函数中手动delete m_timer会触发双重释放崩溃。另外你在Game中new MyTimer时没有传入父对象,会造成MyTimer实例内存泄漏。
  • 构造函数参数不规范:MyTimer构造函数的父对象参数写为QTimer* parent,不符合QObject派生类的规范,父类参数应当定义为QObject*类型,否则传入其他QObject子类作为父对象时会出现类型不匹配问题。

修正后可运行实现

你这个场景下MyTimer本身已经是QTimer的子类,完全没必要额外嵌套一层QTimer实例,直接复用自身的timeout信号即可,简化后代码如下:

  1. 抽象接口类保持不变:
class ISignalHandler
{
public:
    virtual void onTimeout() = 0;
protected:
    virtual ~ISignalHandler() = default;
};
  1. MyTimer头文件修正:
#include <QTimer>
#include "ISignalHandler.h"

class MyTimer : public QTimer
{
    Q_OBJECT // 必须添加元对象宏
public:
    explicit MyTimer(QObject *parent = nullptr); // 父对象参数改为QObject*类型
    void registerTimerSignal(ISignalHandler* callback);
private slots:
    void onTimeout();
private:
    ISignalHandler* m_callback = nullptr; // 初始化空指针避免野指针
};
  1. MyTimer实现文件修正:
#include "MyTimer.h"

MyTimer::MyTimer(QObject *parent)
    : QTimer{parent}
{
    // 直接连接自身的timeout信号,不需要额外嵌套QTimer实例
    connect(this, &QTimer::timeout, this, &MyTimer::onTimeout);
}

void MyTimer::registerTimerSignal(ISignalHandler* callback)
{
    m_callback = callback;
}

void MyTimer::onTimeout()
{
    if (m_callback != nullptr)
    {
        m_callback->onTimeout();
    }
}
// 无需自定义析构函数,没有需要手动释放的堆资源
  1. Game类构造函数修正:
Game::Game(QObject *parent)
    : QObject{parent}
    , m_timer{nullptr}
{
  m_timer = new MyTimer(this); // 传入this作为父对象,由Qt对象树自动管理内存
  m_timer->registerTimerSignal(this);
  m_timer->setInterval(300); // 修正方法名拼写
  m_timer->start();
}

void Game::onTimeout()
{
    run();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 06:31:27