为什么 Qt 信号的参数不能用 typedef 类型定义? [英] why Qt signals' arguments can't be defined with typedef types?

查看:50
本文介绍了为什么 Qt 信号的参数不能用 typedef 类型定义?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于 Qt5/c++11 项目,我使用 QMediaPlayer 对象(名为 audio_player)及其 positionChanged() 信号:

For a Qt5/c++11 project, I'm using a QMediaPlayer object (named audio_player) with its positionChanged() signal:

这段代码没问题:

connect(this->audio_player,
        SIGNAL(positionChanged(qint64)),
        this,
        SLOT(audio_position_changed(qint64)));

但是这个不起作用:

typedef PosInAudio qint64;

connect(this->audio_player,
        SIGNAL(positionChanged(PosInAudio)),
        this,
        SLOT(audio_position_changed(PosInAudio)));

在运行时我收到消息QObject::connect: No such signal QMediaPlayer::positionChanged(PosInAudio)"

At run-time I get the message "QObject::connect: No such signal QMediaPlayer::positionChanged(PosInAudio)"

我很困惑,即使是用 #define 定义的类型也不行:

I was baffled to see that even a type defined with #define wasn't ok:

#define PosInAudio qint64

connect(this->audio_player,
        SIGNAL(positionChanged(PosInAudio)),
        this,
        SLOT(audio_position_changed(PosInAudio)));

(与上面相同的错误信息)

(same error message as above)

这是预期的行为吗?还是我做错了?

Is this the expected behavior ? Or do I make a mistake?

如上所述(感谢 Matteo Italia),如果您使用 Qt5 新的信号槽语法描述 这里.

As explained above (thank you Matteo Italia), everything's ok if you use the Qt5 new signal-slot syntax described here.

推荐答案

问题源于旧式 connect 实际上可以比较 strings 以匹配信号和插槽,这里是信号声明中使用的签名(void positionChanged(qint64)) 和 connect 调用中使用的那个 (void positionChanged(PosInAudio)) 不匹配,如果你是只是比较字符串.

The problem arises from the fact that the old-style connect actually works comparing strings to match the signal and the slot, and here the signature used in the signal declaration (void positionChanged(qint64)) and the one used in your connect call (void positionChanged(PosInAudio)) don't match if you are just comparing strings.

SIGNALSLOT 本质上是字符串化宏(旧式 connect 的实际签名涉及 const char * 或等效的东西);connect 对接收到的字符串执行规范化(删除不必要的空格,const 引用 & co. - 参见 QMetaObject::normalizedSignature - 但同样,不知道 typedefs 或命名空间)并尝试将它们与元对象中的信号/槽列表进行匹配.

The SIGNAL and SLOT are essentially stringifying macros (the actual signature of the old-style connect involves const char * or equivalent stuff); connect performs a normalization on the received strings (removing unnecessary spaces, const references & co. - see QMetaObject::normalizedSignature - but again, with no knowledge of typedefs or namespaces) and tries to match them to the signals/slots lists found in the metaobject.

反过来,这个列表是由 MOC 生成的,它对 C++ 语法和语义的理解相当模糊,并且相当残酷地提取信号和插槽签名;因此,无论是 MOC 生成的字符串还是放入 SIGNALSLOT 宏中的字符串,都不知道诸如 typedef 或等效"之类的细微之处名称(例如,当前命名空间的本地类型,当在外部引用时,需要在命名空间前面加上其名称),因此如果复杂"(和非字面上匹配)类型名称在您的信号和插槽中.

This list, in turn, is generated by the MOC, which has quite a vague understanding of C++ syntax and semantics, and extracts the signal and slots signatures quite brutally; so, neither the strings produced by MOC nor what is put into the SIGNAL and SLOT macros are aware of subtleties like typedefs or "equivalent" names (e.g. a type local to the current namespace, which, when referenced outside, needs to have its name prepended by a namespace), so the connect will fail if you have "complicated" (and non-literally matching) type names in your signal and slots.

新式 (Qt5+) connect(在 @peppe 的评论中提到)应该解决这些问题(并允许像将信号连接到 lambda),但是如果您必须使用旧式 connect 以避免出现问题,您应该始终以相同的方式引用类型 - 例如,如果您在你的信号声明,你也必须在插槽中使用它;如果信号中有命名空间类型,请在它们前面加上足够的命名空间,并在插槽中执行相同操作.

The new-style (Qt5+) connect (mentioned in the comments by @peppe) should solve these issues (and permit neat stuff like connecting a signal to a lambda), but if you have to live with old-style connects to avoid problems you should always refer to types in the same way - e.g., if you use a typedef in your signal declaration, you have to use it in slots too; if you have namespaced types in the signal, prefix them with the adequate namespaces and do the same in the slots.

这篇关于为什么 Qt 信号的参数不能用 typedef 类型定义?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆