Qt Meta-Object System

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就没有问题囉。

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值