您的位置:首页 > 移动开发 > Objective-C

QT特性-QObject、MOC、MOS

2015-04-30 11:30 169 查看
QT特性-QObject、MOC、MOS
sf2gis@163.com
2015年1月7日

1 Meta-Object System元对象系统

目标:Qt的元对象系统提供了QObject的基本功能,包含信号-槽,动态属性,运行时类型信息(RTTI)等。

原理:

QObject提供MOS的功能接口。

Q_OBJECT标识启用元对象系统。

MOC生成元对象系统的标准C++代码。

方法:

QObject::metaObject():返回相关的QMetaObject对象。

QMetaObject::className():返回当前类名(字符串)。

QObject::inherits():判断是否继承自指定类。

QObject::tr()/trUtf8():转码。

QObject::Property()/setProperty():动态属性。

QMetaObject::newInstance():创建新实例对象。

qobject_cast<type *>(obj):高级类型转换,不需要编译器支持RTTI,支持dll。

由于无Q_OBJECT宏时,无法使用QObject的特性,建议无论何时都使用Q_OBJECT。

QMetaObject::connectSlotsByName(this):自动连接机制,将this中槽函数与子对象建立连接。

2 QObject

QObject是所有Qt类的基类。

QObject在释放时会发出destroyed信号。

QObject会对所在线程的所有对象发布信号。

2.1 objecttree/parent-children/ownership

QObject存在对象树,父对象拥有子对象的所有权。

所有权是指父对象释放时,会先将子对象释放。

QObject具有一个objectName属性,可以通过setObjectName()设置。

QObject所属的类可以通过QMetaObject::className()获取。

如果对象树中相关对象被释放,则自动将相关指针设置为0。

示例:

qDebug()<<pListener->objectName ()<<pListener->metaObject()->className ();

2.2 私有的Copy构造函数

所有QObject的子类,无法使用copy构造函数(将copy构造函数设置为私有,无法继承),因为信号槽模式,要求所有的QObject对象是唯一的。

需要使用copy的地方,只能使用指针代替。

如果使用了,会出现以下错误:

error: C2248: 'QObject::QObject' : cannot access privatemember declared in class 'QObject'

参考:http://qimo601.iteye.com/blog/1523936

2.3 属性系统PropertySystem

目标:提供统一,跨编译器和平台的标准属性系统。

原理:由MOS提供。

方法:

Q_PROPERTY(type name

READ getFunction

[WRITE setFunction]

[RESET resetFunction]

[NOTIFY notifySignal]

[DESIGNABLE bool]

[SCRIPTABLE bool]

[STORED bool]

[USER bool]

[CONSTANT]

[FINAL])

属性可以通过MOS读写。

属性可以通过MOS动态的从QObject添加、删除。

声明属性后,在QtCreator中,右击-》重构-》Generate missing Porperties会自动生成声明所有的函数和成员变量(成员变量变自动添加m_前缀)。

示例:

class QTask : public QObject

{

Q_OBJECT

Q_PROPERTY(int iTest READ getTest WRITEsetTest)

private:

int m_iTest;

public:

intgetTest() const

{

returnm_iTest;

}

public slots:

voidsetTest(int arg)

{

m_iTest = arg;

}



2.3.1动态属性添加、删除

目标:在对象中动态添加、删除属性。

方法:setProperty(属性名,值)。

如果值有效,动态属性不存在,则添加动态属性。

如果值有效,属性存在,则改写。

如果值无效(QVariant()默认是无效值),则删除此动态属性,如果此属性不是动态的(显示声明的不是动态的),则无影响。

可以动态的添加属性或删除属性,动态属性只添加到QObject对象中,不影响MetaObject。并且也只能通过动态方法读写。

示例:

QTask *pT= new QTask;

pT->setTest (5);

qDebug()<<pT->getTest ();

int iTest= pT->property ("iTest").toInt ();

pT->setProperty ("abc",77);

int iDyn =pT->property ("abc").toInt ();

pT->setProperty("abc",QVariant());

int iDyn2= pT->property ("abc").toInt ();



2.4 事件系统EventSystem

目标:实现OS中事件的处理。

原理:接收OS事件,处理相应事件。

1) 事件与信号的区别:事件只向事件系统发送,由事件系统唯一分发;而信号则向所有QObject广播,由QObject决定处理。

2) 事件对应Windows中的消息,从OS中获取,然后发送到指定对象。事件循环在一个线程中唯一存在,同步(send)/异步(post)操作事件列表。信号也是同步(directconnect)或异步(queuedconnection)处理连接,如果异步,则等待时间片空闲时,发送异步信号队列。

方法:

1) 处理事件

事件(QEvent类的对象)是各种事件发生时,发送的通知信息。一般响应时需要重写基类的相应的响应函数。

QObject::event()是最顶级的事件处理函数,需要自己判断事件的类型。

2.5 自动连接机制

使用指定的命令方式,moc可以分解将自动建立连接。只能建立在QObject及其子对象之间。

格式:on_ObjectName_Signal(params)。

操作函数:QMetaObject::connectSlotsByName(this)。

详见:qt-信号槽signalslot机制.docx

2.6 QObject与deleteLater()

由于QObject提供了信号-槽机制,在消息循环中需要保持所有对象可用。为了避免在消息循环中引用被释放的指针,Qt对内存的管理引入了deleteLater()来代替delete(),用于保证需要释放的对象在消息循环结束后能够自动释放。

因此,在使用QObject时,需要注意,如果有进入消息循环的slot函数,或者在消息循环中使用的对象,则要使用deleteLater()。

参考:

http://stackoverflow.com/questions/4888189/how-delete-and-deletelater-works-wrt-to-signals-and-slots-in-qt

2.6.1释放QObject

一般在释放时,会将指针置NULL(防止野指针),在使用deteteLater()后,不能直接赋值NULL,应该使用destroyed()信号的响应槽函数置NULL。

参考:

http://stackoverflow.com/questions/6095946/how-can-i-get-the-qobjectdeletelater-to-zero-the-object

示例:

信号

connect(m_pFw,SIGNAL(destroyed()),this,SLOT(nullWatcher()));



void QMapFrameTask::nullWatcher()

{

m_pFw = NULL;

}

3 MOC元对像编译工具

将qt的信号和槽转化为标准的C++代码。

MOC在Qt的bin目录下moc.exe。

使用方法

moc .h文件–o .moc文件

这里.moc文件就是标准的c++头文件。

在使用时,需要将所有使用信号和槽的头文件转化为.moc文件,然后将moc文件包含在头文件中(不要包含在cpp文件中)。

4 信号-槽

参见:qt-信号槽signalslot机制.docx
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: