一 闲谈:编程
熟悉Window下编程的小伙伴们,对其消息机制并不陌生, 话说:一切皆消息。它能够很方便实现不一样窗体之间的通讯,然而MFC库将不少底层的消息都屏蔽了,尽管使用户更加方便、简易地处理消息,但也让人特别是没有Win32编程基的人感到迷茫,不是为什么,笔者也是深受其害的。设计模式
详细描述就不在此展开,感兴趣的请查阅浩瀚如海的资料。。。多线程
二 简要介绍:函数
基于Qt开发,信号槽是确保正常通讯的主要机制,特别是在多线程开发中,线程函数与界面的通讯是没法直接进行的,会存在程序崩溃的问题,笔者在实际开发过程当中也遇到过此问题,利用Qt的信号槽机制能够避免。this
所谓信号槽,相似于设计模式中的观察者模式。当某一事件发生以后,好比,点击了一下PushButton,它就会发出一个信号(signal)。需注意,这种发出是没有目的的,相似广播。若是有对象对这个信号感兴趣,可使用链接(connect)函数进行二者之间的关联,即:发送者发送信号(signal),接收者(感兴趣对象)用本身的一个函数(称之为槽(slot))来处理这个信号。同观察者同样,一个signal能够关联(注册)多个slot,当信号发出时,被链接的槽函数会自动被回调。spa
connect()函数是信号槽机制的关键,下面介绍。线程
三 connect()函数:设计
Qt5与Qt4中对connect()函数的实现有所差别。指针
首先,看Qt4对其实现的定义:code
bool connect(const QObject *, const char *, const QObject *, const char *, Qt::ConnectionType); bool connect(const QObject *, const QMetaMethod &, const QObject *, const QMetaMethod &, Qt::ConnectionType); bool connect(const QObject *, const char *, const char *, Qt::ConnectionType) const
介绍定义1,参数分别为:发送者sender、信号signal、接收者receiver和槽slot,最后一个基本不用。sender 类型是const QObject *,signal 的类型是const char *,receiver 类型是const QObject *,slot 类型是const char *。这个函数将 signal 和 slot 做为字符串处理。
Qt4使用了SIGNAL和SLOT这两个宏,将信号和槽的函数名转换成了字符串。注意,不能将全局函数或者 Lambda 表达式传入connect()。使用字符串致使了Qt4有如下缺点:一旦出现链接不成功的状况,Qt 4 是没有编译错误的(由于一切都是字符串,编译期是不检查字符串是否匹配),而是在运行时给出错误。这无疑会增长程序的不稳定性。
下面,看Qt5对其实现的定义:
QMetaObject::Connection connect(const QObject *, const char *, const QObject *, const char *, Qt::ConnectionType); QMetaObject::Connection connect(const QObject *, const QMetaMethod &, const QObject *, const QMetaMethod &, Qt::ConnectionType); QMetaObject::Connection connect(const QObject *, const char *, const char *, Qt::ConnectionType) const; QMetaObject::Connection connect(const QObject *, PointerToMemberFunction, const QObject *, PointerToMemberFunction, Qt::ConnectionType) QMetaObject::Connection connect(const QObject *, PointerToMemberFunction, Functor);
第一个,sender 类型是const QObject *,signal 的类型是const char *,receiver 类型是const QObject *,slot 类型是const char *。这个函数将 signal 和 slot 做为字符串处理,与Qt4相同,应该是为了兼容性而予以保留的。
第二个,sender 和 receiver 一样是const QObject *,可是 signal 和 slot 都是const QMetaMethod &。咱们能够将每一个函数看作是QMetaMethod的子类。所以,这种写法可使用QMetaMethod进行类型比对。
第三个,sender 一样是const QObject *,signal 和 slot 一样是const char *,可是却缺乏了 receiver。这个函数实际上是将 this 指针做为 receiver,与Qt4相同,应该是为了兼容性而予以保留的。
第四个,sender 和 receiver 也都存在,都是const QObject *,可是 signal 和 slot 类型则是PointerToMemberFunction。看这个名字就应该知道,这是指向成员函数的指针。
第五个,前面两个参数没有什么不一样,最后一个参数是Functor类型。这个类型能够接受static 函数、全局函数以及 Lambda 表达式。
Qt5相比较于Qt4的优点是添加了第4和第5种的重载形式,使得Qt能够在编译期进行错误检查,及早发现问题。