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 ?

  

posted @ 2015-08-20 11:15  aslistener  阅读(316)  评论(0编辑  收藏  举报