Qt RTTI trouble
-
05-07-2019 - |
Question
In a quest for handling events (like mouse moves and clicks) not by subclassing, one has to use installEventFilter
and provide an event handler. While doing so, I've encountered a problem with RTTI support, meaning that typeid().name()
gives QObject *
all the time, no matter on which object event was triggered. There is, of course, another solution---dynamic_cast
followed by null-pointer check, but personally I don't find it clean (and would like to avoid multiple such checks).
To be more specific, here is an example I didn't make to work with Visual C++ with RTTI enabled (/GR):
bool
MousePressInterface::eventFilter
(QObject *obj,
QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress)
{
ColorPicker *sender;
sender = dynamic_cast<ColorPicker *> (obj);
if ( sender )
{
QColor newColor =
QColorDialog::getColor(sender->color());
if ( newColor.isValid() )
sender->setColor( newColor );
Logger::log("color picker clicked");
return true;
}
/* TODO: cleaner way, doesn't work for some reason!
Logger::log(QString("mouse pressed on %1").arg(typeid(obj).name()));
Logger::log(QString(" checking for %1").arg(typeid(ColorPicker *).name()));
if ( typeid(obj) == typeid(ColorPicker * ) )
Logger::log("color picker clicked");
*/
}
Solution
Use qobject_cast
and/or obj->metaObject()->className()
instead.
OTHER TIPS
I would use
if (obj->metaObject() == &ColorPicker::staticMetaObject) {
...
}
if only ColorPicker-instances (and not subclasses of ColorPicker) is be accepted.
If you are accepting subclasses too, use
if (qobject_cast<ColorPicker *>(obj)) {
...
}
The pointer must be dereferenced so that the object it points to is used. Without dereferencing the pointer, the result will be the type_info for the pointer, not what it points to.
Logger::log(QString("mouse pressed on %1").arg(typeid(*obj).name()));
You should normally use typeid
on the dereference of a pointer - the typeid
of a pointer is calculated at compile time and is not normally interesting.
if ( typeid(*obj) == typeid(ColorPicker) )
Logger::log("color picker clicked");
That said, there isn't much difference between what you are doing here, and the dynamic_cast
route - in any case you will have to do dynamic_cast
at some point.