Qt RTTI Probleme
-
05-07-2019 - |
Frage
In einer quest für die Handhabung von events (wie der Maus bewegt und Klicks), nicht durch Unterklassen verwenden installEventFilter
und geben Sie ein Ereignis-handler.Dabei habe ich ein problem mit RTTI-Unterstützung, was bedeutet, dass typeid().name()
gibt QObject *
die ganze Zeit, egal auf welches Objekt Ereignis ausgelöst wurde.Es ist natürlich auch eine Lösung---dynamic_cast
gefolgt von einem null-Zeiger überprüfen, aber ich persönlich finde es nicht sauber (und möchten vermeiden, dass Sie mehrere solcher Prüfungen).Um genauer zu sein, hier ist ein Beispiel, das ich nicht machen, um die Arbeit mit Visual C++ mit RTTI aktiviert (/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");
*/
}
Lösung
Verwenden qobject_cast
und/oder obj->metaObject()->className()
statt.
Andere Tipps
Ich würde verwenden
if (obj->metaObject() == &ColorPicker::staticMetaObject) {
...
}
wenn nur ColorPicker-Instanzen (und nicht den Unterklassen der ColorPicker) ist werden akzeptiert.
Wenn Sie akzeptieren Unterklassen zu verwenden
if (qobject_cast<ColorPicker *>(obj)) {
...
}
Der Zeiger muss aufgelöst werden, so dass das Objekt, das es Punkte verwendet.Ohne Dereferenzierung der Zeiger, wird das Ergebnis der type_info für die Zeiger, nicht das, was es zeigt.
Logger::log(QString("mouse pressed on %1").arg(typeid(*obj).name()));
Sie sollten in der Regel verwenden typeid
auf die Dereferenzierung eines Zeigers - der typeid
der eine Zeiger ist berechnet bei der Kompilierung und ist in der Regel nicht interessant.
if ( typeid(*obj) == typeid(ColorPicker) )
Logger::log("color picker clicked");
Das heißt, es gibt nicht viel Unterschied zwischen dem, was Sie hier tun, und die dynamic_cast
route - in jedem Fall werden Sie zu tun haben dynamic_cast
an einem gewissen Punkt.