• The Meta-Object System


     

    The Meta-Object System

    Meta-Object 提供了用于类间通信的signal/slot, 运行时类型信息、以及动态属性系统。

    Meta-Object 的使用基于以下三个点:

    • QObject 提供了可以使用MetaObject 的一个公共基类。

    • 在类的声明里加入Q_OBJECT 宏, 可以开启类的 MetaObject的诸如signal/slot, 动态属性等特性。

    • Meta-Object Compiler (moc)为 QObject 的子类提供了可以支持Meta-Object的代码。   

    Moc 会为每一个包含了Q_OBJECT宏的类创建一个代码文件, 这个文件能够编译生成obj文件并且链接到类的实现中。

    除了对 signal/slot的支持, meta object 还提供了:

    • QObject::metaObject 返回类的MetaObject类

    • QMetaObject::className  在运行时返回类名字符串, 而不需要RTTI 支持。

    • QObject::inherits  在Object继承树种确定某对象是否是某个类的实例

    • QObject::property 通过名称查询和设置属性值

    • QMetaObject::newInstance 创建一个类的实例

    QMetaObject 支持在QObject 上使用 qobject_cast, qobject_cast 的作用和 C++ 的 dynamic_cast 相同, 但它不需要 RTTI支持, 并且能够在不同的动态链接库之间使用。

    可以在QObject的子类中不适用 Q_OBJECT 宏, 它会导致所有meta-object的特性都不被支持, 从 meta-object 来看, 一个未使用 meta-object的类与离它最近的使用meta-object 的祖先是一样的。 比如, 在这个类中使用 className, 会返回这个祖先的类名。

    Meta-Object Compiler

    Moc 是用于处理Qt 的c++ 扩展的程序。

    Q_FLAG 宏声明可以用做flag 的enum。 Q_CLASSINFO 可以为 meta-object添加name-value 对。

    Moc产生的文件和其它C++源文件一样必须被编译、链接,否则, 在链接阶段会出错。 如果使用qmake, 它会遍历项目中的头文件并为那些包含了Q_OBJECT 宏的文件添加moc规则。

    一般推荐使用 自动配置的moc, 它能够通过qmake生成的makefile去控制所有的moc步骤。

    如果需要自己写makefile, 可以在GNU make中如下描述:

    moc_%.cpp: %.h

            moc $(DEFINES) $(INCPATH) $< -o $@

     或者可以简化为

    moc_foo.cpp: foo.h

            moc $(DEFINES) $(INCPATH) $< -o $@

    必须记得要把 moc_foo.cpp 添加到 SOURCES 变量中, 把 moc_foo.o或者 moc_foo.obj添加到 OBJECTS变量中。

    两个例子都假设 DEFINES INCPATH 声明的是 define 和 include 路径, 并被传入到 C++ 编译器中。

    Moc 的使用可以在 Qt manual 中 the meta-object system 中找到。

    当然也可以使用其它后缀名, 例如 .c  .cc  .CC  .cxx .c++等。

    可以在文件中使用

     #ifndef Q_MOC_RUN

        ...

    #endif

    来通知moc跳过这一段代码。

    Moc 能够识别出使用 Q_OOBJECT 宏的类中的一些危险和错误。 但是如果是链接错误, 可能是 className未声明, 或者缺少虚函数表。最常见的是没有添加 moc生成的C++代码。

    Moc并非支持所有 C++ 语法

    • moc不支持模板;

    • 需要在多继承中把QObject写在最前面, 并且只允许第一个类是Object。

    • 函数指针不能用作signal/slots的参数

    • 在使用 enum 和 typedef 时, 必须使用完整的定义。 比如在signal参数中, MyClass::MyEnum  和 MyEnum  是两个不同的类型。因此在signal/slots 的声明、connect时, 必须使用完整的类型。

    • 嵌套类不能使用 signal/slots

    • Signal/slots的返回值会被当作void处理, 因此无法访问。

    • 在 signal/slots区域内, 只能出现信号、槽。

    Qt 使用 moc 实现 signal / slot, 并对于它的原因有专门的篇幅描述。 可以参看 Qt-mannual 中 why does Qt use Moc for signals and slots ?

      

  • 相关阅读:
    layer子层给父层页面元素赋值,以达到向父层页面传值的效果
    根据HttpServletRequest获取用户真实IP地址
    KVM--安装及初步使用
    eslint 踩坑 -- error '***' is assigned a value but never used no-unused-vars
    eslint 效验规则
    leetcode407接雨水II
    leetcodej剑指offer41.数据流中的中位数
    leetcode44通配符匹配
    leetcode955K连续位的最小反转次数
    leetcode638大礼包
  • 原文地址:https://www.cnblogs.com/aslistener/p/4744579.html
Copyright © 2020-2023  润新知