QT中如何在接口类声明信号、子类发射并连接到槽函数
问题解决
核心错误点
- Qt的信号不允许声明为纯虚函数:信号的实现代码由Qt的moc工具自动生成,你在接口类中给
getData信号加virtual = 0会导致moc无法生成正确的实现逻辑,信号触发和连接都会失效。 - 旧版
SIGNAL/SLOT宏写法错误:使用宏连接信号槽时,必须完整填写函数的参数类型,不能只写函数名。 - 多余的类型转换:你的
InstrumentsCommunication已经继承了QObject,所以instrComm本身就是QObject*类型,不需要额外做dynamic_cast转换。
修正步骤
1. 修改接口类信号声明
去掉信号的纯虚标记,不需要加virtual(Qt5及以上版本信号默认支持重写,不需要显式加virtual):
class InstrumentsCommunication : public QObject { Q_OBJECT public: virtual bool open(const std::string addr) = 0; virtual void transaction(Command cmd, qint16 rate) = 0; signals: // 去掉纯虚标记,建议参数加const引用减少拷贝 void getData(const QString &s); private: virtual void write(const std::string cmd) = 0; }; Q_DECLARE_INTERFACE(InstrumentsCommunication, "InstrumentsCommunication")
2. 简化实现类的信号声明
父类已经定义了信号,子类不需要重复声明,直接在代码中emit即可,如果你要保留override声明,需要保证签名和父类完全一致:
class SerialCommunication : public InstrumentsCommunication { Q_OBJECT Q_INTERFACES(InstrumentsCommunication) public: SerialCommunication(); bool open(const std::string addr) override; void transaction(Command cmd, qint16 rate) override; // 可以删掉重复的getData信号声明,父类已经继承过来了 public slots: void read(); private: QSerialPort serial; QString buffer; void write(const std::string cmd) override; };
3. 修正信号槽连接写法
优先用新版函数指针写法,有编译期检查,报错更直观:
bool Creator::open(const std::string addr){ instrComm = this->FactoryMethod(); // 推荐写法,编译期检查参数匹配 QObject::connect(instrComm, &InstrumentsCommunication::getData, this, &Creator::recvData); // 旧版宏写法,要写全参数类型,不推荐使用 // QObject::connect(instrComm, SIGNAL(getData(QString)), this, SLOT(recvData(QString))); bool isConn = instrComm->open(addr); return isConn; }
额外注意事项
- 所有包含
Q_OBJECT宏的头文件,必须加入到项目构建系统的扫描范围:qmake项目要把头文件加到.pro的HEADERS变量中,CMake项目要开启AUTOMOC配置,否则moc无法生成信号的实现代码,信号槽依然会失效。 - 信号和槽的参数签名必须完全匹配,否则连接会失败。
内容的提问来源于stack exchange,提问作者cle
相关产品推荐
相关产品推荐

