对象模型 ######################################## Qt对象模型(Object Model, meta-object system)是Qt的核心思想。其本质是为了弥补C++在GUI编程方面不够柔韧的缺点。Qt的对象模型主要优点如下: - 信号和槽 :提供了对象间交互机制 - 属性系统 :提供了编译时/运行时对象属性 - 事件机制 - 基于上下文的国际化字符串翻译 - 定时器 : 为事件驱动提供便利 - 对象树: 为对象模型提供了层次结构 - 动态转换 : 允许跨越库文件进行类型转换 对象模型为对象提供了 ``标识(identity)`` 的概念以区分 ``值(value)`` 的概念。值与概念不同之处在于: - 值是可复制的、可赋值的 - 标识是可克隆的。 由于对象模型中的类使用标识概念而不是值的概念,因此,Qt对象的 ``复制构造函数`` 和 ``operator=`` 函数被禁用。 .. note:: 将对象看作标识,意味着将考虑: - Qt对象所拥有的 ``QObject::objectName()`` - Qt对象在对象层次中所占有的位置 - Qt对象连接的槽和发射的信号 - Qt对象运行时所添加的属性 由于以上原因,Qt对象应当被当作一个标识看待,而不是简单的、可随意复制的值。 QObject **************************************** QObject是Qt对象模型的核心。与Java类似,QObject是所有Qt对象的基类。QObject为Qt的对象模型提供了以下功能: [#]_ - 通过 \ `connect() `_ 和 \ `disconnect() `_ 函数提供了对象间通信机制(信号和槽)。 - 通过 \ `event() `_ 和 \ `eventFilter() `_ 函数提供了事件机制 - 通过 \ `children() `_ 和 \ `parent() `_ 提供了对象模型的可用于管理内存的层次结构 - 通过 \ `inherits() `_ 、 \ `isWidgetType() `_ 和 \ `isWindowType() `_ 提供了运行时类型识别 - 通过 \ `objectName() `_ 、 \ `dumpObjectInfo() `_ 、 \ `setProperty() `_ 提供了对象识别机制 QObject提供了以下便利宏: - ``Q_CLASSINFO(Name, Value)``:为类添加额外信息,例如: .. code-block:: c++ class MyClass : public QObject{ Q_OBJECT Q_CLASSINFO("Author", "Pierre Gendron") Q_CLASSINFO("URL", "http://www.my-organization.qc.ca") ... }; .. note:: 被添加的信息可以通过 ``metaObject()`` 获取: .. code-block:: c++ const QMetaObject* classinfo = this->metaObject(); int num = classinfo->classInfoCount(); for (int i = 0; i < num; ++i) { qDebug()<classInfo(i).name(); } - ``Q_DISABLE_COPY(Class)`` :禁用类的拷贝函数和 ``operator=`` 函数 .. note:: 与此类似,还存在 ``Q_DISABLE_MOVE(Class)`` 和 ``Q_DISABLE_COPY_MOVE(Class)`` 宏 - ``Q_ENUM(...)`` :将枚举类型注册到元对象系统,当将枚举值储存到 ``QVariant`` 时可以被转换为字符串。使用qDebug()输出时也会被输出为字符串。这个宏要求在声明过 ``Q_OBJECT`` 或 ``Q_GADGET`` 的类中使用,并且必须位于被声明的枚举之后。 .. [#] \ `qt5-doc-QObject Class `_ qobject_cast vs dynamic_cast **************************************** .. admonition:: 总结自 - `qobject_cast() vs dynamic_cast() | Qt Forum `_ 简单地来说,相比 dynamic_cast 而言,qobject_cast 有以下优势: - 不需要 RTTI 支持 - 可跨越动态库边界 - 可能比 dynamic_cast 快 5 - 10 倍