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

网站虚拟主机购买教程专业网站设计工作室

网站虚拟主机购买教程,专业网站设计工作室,网站运营需要什么行业技术,免费域名注册网站有哪些问题如题目所示:QMetaObject::invokeMethod: No such method xxxx,在网上好一顿查,又将查到的资料喂给了 Ai,才最终将问题解决,特此记录下。 一、问题背景 在做公司项目时,使用了插件的方式开发。主程序加载…

问题如题目所示:QMetaObject::invokeMethod: No such method xxxx,在网上好一顿查,又将查到的资料喂给了 Ai,才最终将问题解决,特此记录下。

一、问题背景

在做公司项目时,使用了插件的方式开发。主程序加载了一个叫CtmAboutAppPlugin的插件。该插件有个界面类CtmAboutUi,它有个槽函数:

public slot:void subAppInfo(const QVariant& msg);

主程序通过一个叫 CbbEventBus的事件总线机制,把消息发送给CtmAboutAppPlugin 这个插件。

此处我给出CbbEventBus的订阅方法的源码(问题出在了订阅方法这里):

bool CbbEventBus::subscribe(const QString &topic, QObject *receiver, const char *method, Qt::ConnectionType type)
{if (!receiver || !method) return false;auto connection = QObject::connect(this,&CbbEventBus::signalUpdateMessage,receiver,[receiver, method, topic](const QString &receivedTopic, const QVariant &msg) {if (receivedTopic == topic) {// 问题出现在下面这里// QMetaObject::invokeMethod(receiver, method, Q_ARG(const QVariant&, msg)); // 最开始我是这么写的QMetaObject::invokeMethod(receiver, method, Q_ARG(QVariant, msg)); 	// 后来改成了左边这样}},type);if (connection) {m_QIsSubscribeMap[topic][receiver].append(connection);return true;}return false;
}

上面两种写法,在程序运行时,控制台分别输出以下信息:

Q_ARG(QVariant, msg)对应控制台输出信息:QMetaObject::invokeMethod: No such method CtmAboutUi::1subAppInfo(QVariant)(const QVariant&)

Q_ARG(QVariant, msg)对应控制台输出信息:No such method CtmAboutUi::1subAppInfo(QVariant)(QVariant)

二、🔍 问题原因(一句话总结)

根本原因不是方法不存在,而是 invokeMethod 找方法时用的名字“对不上号”——我传了个“带参数的签名”,它却以为这是“方法名”,导致匹配失败。


三、🕵️‍♂️ 排查过程回顾

3.1 第一反应:是不是 MOC 没生效?

○ 检查了 CtmAboutUi 类,Q_OBJECT 有,public slots: 有,语法没问题。
○ 打开 Qt 生成的 moc_CtmAboutUi.cpp一看,MOC 确实生成了,subAppInfo(QVariant) 也注册进去了,说明元对象系统这块是没有问题的。
在这里插入图片描述

3.2 第二反应:是不是 Q_ARG 写错了?

○ 一开始用了 Q_ARG(const QVariant&, msg),这是个经典坑。
○ Qt 的 Q_ARG 第一个参数是类型名,不能带 const&(否则元对象系统会直接按照 const QVariant&去匹配字符串,实际上元对象系统中注册的是QVariant 类型,并没有const QVariant&),应该写成 Q_ARG(QVariant, msg)
○ 改了之后,错误还在,但变成了 (QVariant)(QVariant),说明问题没完。

3.3 第三反应:名字到底传了啥?

eventBus.subscribe(topic, m_pAboutUi, SLOT(subAppInfo(QVariant)));

○ 这里 SLOT(...) 宏展开后是 "subAppInfo(QVariant)",是个带参数列表的字符串。
○ 而 invokeMethod 拿到这个字符串后,会把它当“方法名”去查,再配上 Q_ARG(QVariant, msg),就变成了"subAppInfo(QVariant)" + “(QVariant)”,即下面这样:

subAppInfo(QVariant)(QVariant)

这当然找不到,因为实际注册的是 subAppInfo(QVariant)

四、✅ 最终解决办法

把调用方式从:

eventBus.subscribe(this->topic(), m_pAboutUi, SLOT(subAppInfo(QVariant)));

改成:

eventBus.subscribe(this->topic(), m_pAboutUi, "subAppInfo");

只传方法名,不带参数列表。这样 invokeMethod 就会用方法名 “subAppInfo” 去找,再根据 Q_ARG(QVariant, msg) 匹配参数类型,完美匹配成功。


4.1 其它疑问:

我也尝试了如下方法:

虽然 "subAppInfo" 能解决问题,但更推荐用 函数指针 的方式,既安全又现代:


eventBus.subscribe(this->topic(), m_pAboutUi, &CtmAboutUi::subAppInfo);

这需要 CbbEventBus 支持模板,但好处是:
● 编译时检查,名字写错直接报错
● 不用拼字符串,不怕类型不匹配
● IDE 能跳转,维护方便

但是有错误,没有成功…


五、📝 总结

QMetaObject::invokeMethod: No such method 不一定是方法不存在,很可能是 名字传错了。
SLOT() 宏返回的是带参数的字符串,不适合直接传给 invokeMethod 当方法名用。
Q_ARG 只写类型名,别带 const&
个人认为最稳妥的方式是用函数指针 &Class::method,但是该方法没有成功,由于工作时间问题,目前还没继续深究…

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

相关文章:

  • 数据库管理-第376期 Oracle AI DB 23.26新特性一览(20251016)
  • 【Nature高分思路速递】 物理驱动的机器学习
  • word文档转pdf开源免费,可自定义水印
  • k8s(五)PV和PVC详解
  • 深度学习与自然语言处理
  • python 部署可离线使用的中文识别OCR(window)
  • 湖州微信网站建设网站301了不知道在哪做的
  • 请描述网站开发的一般流程图php网站开发经理招聘
  • 关于pkg-config的使用示例--g++编译过程引入第三方库(如Opencv、Qt)
  • 外贸soho先做网站wordpress如何把背景颜色调为白色
  • zk02-知识演进
  • 全自动相机在线标定方法
  • 设计模式篇之 中介者模式 Mediator
  • 卫星几何处理
  • 【个人成长笔记】在Ubuntu中的Linux系统安装sogoupinyin搜狗输入法完整版(亲测有效)
  • 3d驱动模型。如何让人物说话?什么情况下需要训练wav2lip模型,自己训练的好处是什么?操作步骤是?
  • 画册什么网站做方便做外汇著名网站
  • CRMEB标准版PHP订单发货全解析
  • Flink 窗口 Join 与区间 Join 实战详解
  • 分布式监控体系:从指标采集到智能告警的完整之道
  • 《Muduo网络库:实现one loop per thread设计模式》
  • 怎么注册网站卖东西哪有培训网站开发
  • makefile概述
  • 用R处理nc文件
  • GaussDB DN动态内存使用满导致DN主备切换
  • 湖南微网站开发北京市建设规划网站
  • TCP与UDP:传输层双雄的核心对比
  • 安化网站建设怎样建个人网站 步骤
  • 并查集-547.省份的数量-力扣(LeetCode)
  • 生命周期全景图:从componentDidMount到getSnapshotBeforeUpdate