zoukankan      html  css  js  c++  java
  • Qt MetaObject System

    转自:http://blog.sina.com.cn/s/blog_640531380100sikl.html


    Qt的Meta-Object System提供了signals/slots机制中,物件之间能够做联繫、run-time type informaion以及dynamic property system…等功能。

    Meta-Object System 的基础如下:

    1. QObject 类别为所有物件的基础类别(才能够使用meta-object system)
    2. Q_OBJECT macro(巨集),置于类别宣告中的private区域中,如此才能够使用meta-object大部分功能,包括dynamic properties、signals、slots
    3. Meta-Object Compiler (moc) 产生QObject子类别所需的程式码,如此才能够执行meta-object的功能

    moc 会读取C++原始档,如果它发现一或多个类别宣告有包含Q_OBJECT macro(就是宣告时,有写macro)时,就会产生出另外的C++档,这个档提供了这些类别的meta-object程式码,通常会被include 进类别原始档,或是以较常见的方式被compile与link于类别实做中。

    除了提供signals/slots机制之外,meta-object程式码亦提供下列额外的功能:

    * QObject::metaObject() 会回传此类别相关的meta-object
    * QMetaObject::className() 会在run-time时回传类别名称(字串型态),而不需要C++ compiler所支援的native run-time type information(RTTI)
    * QObject::inherits() 当一个物件是继承自某特定类别的子类别(为QObject继承的顺序)的instace时,此函式会return
    * QObject::tr() 和 QObject::trUtf8() 会将字串做翻译处理
    * QObject::setProperty() 和 QObject::property() 会动态根据名称设定与取得property

    在使用QObject类别的 qobject_cast 时,也可能会执行动态的型态转换(dynamic cast)。qobject_cast()函式类似于标准C++的dynamic_cast(),但有不需要RTTI支援的优点,此外也可以运作于夸动态 函式库(dynamic library)的范围。它将会把参数转换为指标型态(会用”<>”符号来标示),如果物件是正确的 型态(在run-time时)回传一个非null的指标;但如果物件型态不相容,则回传null指标。

    举例说明,假定MyWidget是继承字QWidget,并且在宣告时有加入Q_OBJECT macro:

    QObject *obj = new MyWidget;

    则资料型态是QObject * 的变数obj,实际上是指向MyWidget的指标,我们可用下列方式做型态转换:

    QWidget *widget = qobject_cast<QWidget *>(obj);

    因为物件实为MyWidget(QWidget的子类别),所以这样的型态强制转换并无错误。既然我们知道obj是MyWidget,就可以直接强 制转换到MyWidget *:

    MyWidget *myWidget = qobject_cast<MyWidget *>(obj);

    因为qobject_cast()会将内建的Qt型态与自行建立的型态(此例中的MyWidget)视为相同,所以这样的型态强制转换并无错误。

    QLabel *label = qobject_cast<QLabel *>(obj);
    // label is 0

    但上面的强制转换却会将指标设为null。

    不过Qt中,可以在run-time时,根据型态来处理不同型态物件之间的转换:

    if (QLabel *label = qobject_cast<QLabel *>(obj)) {
    label->setText(tr(”Ping”));
    } else if (QPushButton *button = qobject_cast<QPushButton *>(obj)) {
    button->setText(tr(”Pong!”));
    }

    值得注意的一点,如果没有Q_OBJECT macro,除了不能自行定义signals/slots之外,其他上述的功能亦将无法使用。从meta-object system的观点来看,如果 QObject 的子类别没有meta code的话,QMetaObject::className()将不回传你的类别名称,而是类别的祖先的名称。因此,这边建议即便没有使用 signals/slots机制,或其他相关的功能,在QObject的子类别还是把Q_OBJECT macro引进来使用比较好。

    可参考QMetaObjectQt’s Property System 以及 Signals and Slots

    *注意:

    由于qmake并不会处理 .cpp中的Q_OBJECT(通常也很少有人会把Q_OBJECT写在.cpp,而是写在.h中),所以,如果.cpp中有Q_OBJECT的话,则会 产生出 undefined reference to ‘vtable for xxx 这种错误,解决方法就是自己用moc来来处理.cpp中的Q_OBJECT(但官方似乎不太建议自己用moc来处理,而是把Q_OBJECT放在.h档 中),但这边还是说明一下要怎麽自己动手用moc。

    * 若xxx.cpp中包含有O_OBJECT,可以先用下面的指令来处理当中的Q_OBJECT

    moc xxx.cpp -o xxx.moc

    * 接着输入qmake -project、qmake,若没事可以看看Makefile中,已经针对xxx.moc有作处理囉,类似如下

    xxx.moc: xxx.cpp
    /opt/qtsdk-2009.01/qt/bin/moc $(DEFINES) $(INCPATH) xxx.cpp -o xxx.moc

    * 最后只需要把 #include “xxx.moc” 放到 xxx.cpp 最尾端(一定要放最后一行),然后再make就没有问题囉。


  • 相关阅读:
    NOI2005瑰丽华尔兹
    BZOJ4919[Lydsy1706月赛]大根堆
    BZOJ1097[POI2007]ATR-Tourist Attractions
    Luogu2973 [USACO10HOL]Driving Out the Piggies G
    Luogu5505 JSOI2011分特产
    Luogu1450 HAOI2008硬币购物
    NOI2001 炮兵阵地
    汕头市队赛 SRM 09 A 撕书
    洛谷P1196 银河英雄传说
    洛谷P3144 [USACO16OPEN]关闭农场Closing the Farm
  • 原文地址:https://www.cnblogs.com/pamxy/p/2991506.html
Copyright © 2011-2022 走看看