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