why Qt signals' arguments can't be defined with typedef types?

拜拜、爱过 提交于 2019-12-10 13:46:41

问题


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

This piece of code is ok:

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

But this one doesn't work:

typedef PosInAudio qint64;

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

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

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?


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


回答1:


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.

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.

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.

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.



来源:https://stackoverflow.com/questions/25402685/why-qt-signals-arguments-cant-be-defined-with-typedef-types

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!