Qt RTTI проблема
-
05-07-2019 - |
Вопрос
В поисках обработки событий (например, движений мыши и щелчков) не путем создания подклассов, необходимо использовать installEventFilter
и предоставить обработчик событий. При этом я столкнулся с проблемой поддержки RTTI. Это означает, что typeid (). Name ()
постоянно выдает QObject *
, независимо от того, какое событие объекта был вызван. Есть, конечно, другое решение - dynamic_cast
, за которым следует проверка нулевого указателя, но лично я не нахожу это чистым (и хотел бы избежать нескольких таких проверок).
Чтобы быть более конкретным, вот пример, который я не сделал для работы с Visual C ++ с включенным RTTI (/ 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");
*/
}
Решение
Используйте qobject_cast
и / или obj-> metaObject () - > className ()
.
Другие советы
Я бы использовал
if (obj->metaObject() == &ColorPicker::staticMetaObject) {
...
}
если принимаются только экземпляры ColorPicker (а не подклассы ColorPicker).
Если вы также принимаете подклассы, используйте
if (qobject_cast<ColorPicker *>(obj)) {
...
}
Указатель должен быть разыменован, чтобы использовать объект, на который он указывает. Без разыменования указателя результатом будет указатель type_info для указателя, а не то, на что он указывает. Р>
Logger::log(QString("mouse pressed on %1").arg(typeid(*obj).name()));
Обычно вы должны использовать typeid
для разыменования указателя - typeid
для указателя вычисляется во время компиляции и обычно не интересен.
if ( typeid(*obj) == typeid(ColorPicker) )
Logger::log("color picker clicked");
Тем не менее, нет большой разницы между тем, что вы здесь делаете, и маршрутом dynamic_cast
- в любом случае вам придется выполнить dynamic_cast
в какой-то момент . р>