Problema Qt RTTI
-
05-07-2019 - |
Domanda
In una ricerca per la gestione di eventi (come mosse e clic del mouse) non tramite la sottoclasse, è necessario utilizzare installEventFilter
e fornire un gestore di eventi. Nel fare ciò, ho riscontrato un problema con il supporto RTTI, nel senso che typeid (). Name ()
fornisce sempre QObject *
, indipendentemente dall'evento oggetto è stato attivato. Esiste, ovviamente, un'altra soluzione --- dynamic_cast
seguita da un controllo null-pointer, ma personalmente non lo trovo pulito (e vorrei evitare molteplici controlli di questo tipo).
Per essere più specifici, ecco un esempio che non ho fatto funzionare con Visual C ++ con RTTI abilitato (/ 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");
*/
}
Soluzione
Usa qobject_cast
e / o obj- > metaObject () - > className ()
invece.
Altri suggerimenti
Vorrei usare
if (obj->metaObject() == &ColorPicker::staticMetaObject) {
...
}
se vengono accettate solo istanze ColorPicker (e non sottoclassi di ColorPicker).
Se si accettano anche sottoclassi, utilizzare
if (qobject_cast<ColorPicker *>(obj)) {
...
}
Il puntatore deve essere dereferenziato in modo che venga utilizzato l'oggetto a cui punta. Senza dereferenziare il puntatore, il risultato sarà type_info per il puntatore, non ciò a cui punta.
Logger::log(QString("mouse pressed on %1").arg(typeid(*obj).name()));
Normalmente dovresti usare typeid
sulla dereference di un puntatore - il typeid
di un puntatore viene calcolato al momento della compilazione e normalmente non è interessante.
if ( typeid(*obj) == typeid(ColorPicker) )
Logger::log("color picker clicked");
Detto questo, non c'è molta differenza tra quello che stai facendo qui e il percorso dynamic_cast
- in ogni caso dovrai fare dynamic_cast
ad un certo punto .