例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| #include <QCoreApplication> #include <QDebug> #include <typeinfo> class Base : public QObject { Q_OBJECT public: explicit Base(QObject *parent = 0) {} }; class Foo : public Base { Q_OBJECT public: Foo(QObject *parent = 0) : Base(parent) {} }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Base *obj = new Foo(); auto b = qobject_cast<Base *>(obj); qDebug() << (b != nullptr); qDebug() << obj->metaObject()->className(); qDebug() << typeid(obj).name(); return a.exec(); } #include "main.moc"
|
输出结果:
不难看出,当需要明确根据类型进行不同逻辑时,可能会产生意想不到的问题。
在我们的项目中,有一个表单类TUiLoader。有两个控件类,分别是TLineEdit和TDateTimeEdit。
大概长这样:
1 2 3 4 5 6 7 8 9
| class TLineEdit {}; class TDateTimeEdit : public TLineEdit {}; class TUiLoader : public QFrame { Q_OBJECT public: void doSomething(QObject *obj); private: QList<QObject *> objs; }
|
当我们在doSomething
函数中要根据不同的类型进行不同逻辑时,例如:
1 2 3 4 5 6 7
| void TUiLoader::doSomething(QObject *obj) { if (qobject_cast<TLineEdit *>(obj)) { } else if (qobject_cast<TDateTimeEdit *>(obj)) { } }
|
危险!TDateTimeEdit当然可以转换成TLineEdit, 因此执行了TLineEdit的逻辑,这并不是我想要的。
如何解决?
可以在doSomething
中调换判断的顺序,或者用元对象的className进行RTTI。