绕过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信号即可,简化后代码如下:
- 抽象接口类保持不变:
class ISignalHandler { public: virtual void onTimeout() = 0; protected: virtual ~ISignalHandler() = default; };
- 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; // 初始化空指针避免野指针 };
- 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(); } } // 无需自定义析构函数,没有需要手动释放的堆资源
- 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
相关产品推荐
相关产品推荐

