对象模型
标准 C++ 对象模型为对象范式提供了非常高效的运行时支持。但是,在某些问题域中,它的静态特性不够灵活。图形用户界面编程是一个需要运行时效率和高度灵活性的领域。Qt通过将C++的速度与Qt对象模型的灵活性相结合,提供了这一点。
Qt为C++添加了以下功能:
- 一种非常强大的无缝对象通信机制,称为信号与槽。
- 可查询和可设计的对象属性。
- 强大的事件和事件过滤器。
- 国际化的上下文字符串翻译。
- 高级的定时器,可以优雅地将许多任务集成到事件驱动的GUI中。
- 分层和可查询的对象树,以自然的方式组织对象所有权。
- 受保护的指针(QPointer),当引用的对象被销毁时自动设置为0,与普通的C++指针不同,普通指针在对象被销毁时变为悬空指针。
- 可跨库边界使用的动态转换。
- 支持自定义类型创建。
这些Qt特性中的许多都是使用标准C++技术实现的,基于从 QObject 继承。其他特性,如对象通信机制和动态属性系统,则需要Qt自身的元对象系统提供的元对象系统。
元对象系统是C++的扩展,使该语言更适合真正的组件GUI编程。
重要的类
这些类构成了 Qt 对象模型的基础。
QMetaClassInfo | 关于类的附加信息 |
---|---|
QMetaEnum | 枚举器的元数据 |
QMetaMethod | 成员函数的元数据 |
QMetaObject | 包含有关 Qt 对象的元信息 |
QMetaProperty | 属性的元数据 |
QMetaType | 在元对象系统中管理命名类型 |
QObject | 所有 Qt 对象的基类 |
QObjectCleanupHandler | 监视多个 QObject 的生存周期 |
QPointer | 为 QObject 提供受保护的指针的模板类 |
QSignalBlocker | QObject::blockSignals() 的异常安全封装 |
QSignalMapper | 将可识别发送者的信号捆绑在一起 |
QVariant | 对于最常见的 Qt 数据类型,起到联合的作用 |
Qt 对象:本体与值
上面列出的 Qt 对象模型的一些新增功能要求我们将 Qt 对象视为本体,而不是值。值可以被复制或赋值;而本体则被克隆。克隆意味着创建一个新的本体,而不是原来的精确复制。例如,双胞胎具有不同的本体。它们可能看起来一模一样,但是它们有不同的名字、不同的位置,甚至可能拥有完全不同的社交网络。
因此,对本体进行克隆比复制或赋值更为复杂。我们可以从 Qt 对象模型中看到这意味着什么。
一个 Qt 对象…
- 可能有一个唯一的 QObject::objectName()。如果我们复制一个 Qt 对象,我们应该给副本取什么名字?
- 在对象层次结构中有一个位置。如果我们复制一个 Qt 对象,副本应该放在哪里?
- 可以连接到其他 Qt 对象以向它们发出信号,或接收它们发出的信号。如果我们复制一个 Qt 对象,应该如何将这些连接传递给副本?
- 可以在运行时添加新属性,这些属性在 C++ 类中没有声明。如果我们复制一个 Qt 对象,副本是否应该包含添加到原始对象的属性?
因此,Qt 对象应该被视为本体,而不是值。本体是被克隆的,而不是被复制或赋值,而克隆本体是一个比复制或赋值更为复杂的操作。因此,QObject 和所有 QObject 的子类(直接或间接)都禁用了它们的复制构造函数和赋值运算符。