总结Qt中三大机制(一):信号与槽机制

时间:2025-03-30 09:34:21

最近复习了一下Qt,重点是它的三大机制:信号与槽,内存管理,事件处理。其中个人认为事件处理又是难点,它涉及到Windows中的消息机制。因篇幅有限,我会分开来讲。本篇文章讲解的是信号与槽机制。

首先介绍,信号与槽是Qt中的一种通信机制,应用于对象之间的通信,可以是同一个对象,可以是同类的不同对象,也可以是不同类的对象,而原生的C++想要实现对象之间通信还是很麻烦的,所以你看,Qt还是很厉害的!

信号与槽机制独立于标准的C++,是标准C++的扩展,就像C++11是对C++98的扩展。因此要想正确的处理信号与槽,必须借助moc(Meta Object Compiler),即元对象编辑器,这是一个C++预处理程序,它能为高层次的事件处理自动生成所需要的附加代码。同时要想实现信号与槽,必须在头文件中添加宏Q_OBJECT,必须在头文件中这个宏才能被展开。

1.信号与槽机制

1. is 信号?

what is 信号?为什么我们点击QPushButton按钮,它就能发出一个clicked()信号,同时有相应的槽函数被调用执行?

当用户的操作(如点击、输入)使得某个对象的内部状态发生改变时,信号就会被发出。至于这个信号是如何发出的?信号的本质又是什么?我想作为一个初级开发者暂时不必研究这么深刻的问题,目前只需要知道某个对象可以发出哪些信号以及如何使用,即可。

我想关于信号可以归纳出以下几点:

  • 从形式上看,信号很像标准C++中的函数一样,但是信号是没有函数体定义的;
  • 信号的返回类型都是void,不要指望能从信号返回什么有用的信息;
  • 关键字signals表示进入了信号声明区,在其后面即可声明信号;
  • 信号不存在访问权限的问题,即不受public、protected、private的限制;
  • 除了系统预定义好的信号,我们还可以自定义信号,使用emit关键字就可以发射:emit clicked() 。

 

1.2.槽函数

槽函数跟C++中的成员函数很像,也可以通过类对象被调用。但比较牛的一点是,槽函数与信号连接之后,一旦信号发出,该槽函数就会被自动调用执行。

关键字slots意味着进入了槽函数声明区,在其后即可声明或者定义槽函数。

槽函数也存在访问权限问题,即public、protected、private:

  • public slots:此区域声明的槽函数表示任何对象发出的信号都可以与之连接;
  • protected slots:此区域声明的槽函数表示当前类及其子类的对象可以将信号与之连接;
  • private slots:此区域声明的槽函数表示只有当前类的对象可以将信号与之连接。

 

1.3.使用connect()函数将信号和槽函数连接

声明好了信号(使用系统预定义好的也可以),定义好了槽函数,下面只需要使用connect()函数将它们连接起来即可。

connect()是QObject对象的成员函数,它的声明如下:

static QMetaObject::Connection QObject::connect(const QObject *sender, const QMetaMethod &signal,const QObject *receiver, const QMetaMethod &method, Qt::ConnectionType type = Qt::AutoConnection)

看起来这个声明还挺复杂的,其实使用起来很简单,只要记住:connect(发送者,信号,接收者,槽函数)即可。其中第五个参数因为有默认值,一般不做修改。也要注意,发送者和接收者位置的参数是个指针类型,即某个对象的地址。

有几点归纳如下:

  • 信号必须使用宏SIGNAL()包装,槽函数必须使用宏SLOT()包装;
  • 一个信号可以与多个槽函数连接,即此信号发出时,这些槽函数会一个接一个执行,但是它们的执行顺序是不确定的,并且我们不能人为指定;当然,多个信号也可以与一个槽函数连接,只要其中一个信号发出,就会执行该槽函数;
  • 在非多线程对象之间,使用的是直接链接方式,即只有当所有的槽函数返回以后发射函数才返回。多线程之间对象的信号槽链接,是以队列的方式连接,即发射信号后不需要等待槽返回。
  • 如果想要断开信号与槽函数的连接,使用disconnect()函数,参数和connect()函数一样的。

从上面也可以看出,只有QObject类的对象或其派生类对象才能使用信号与槽机制,再次强调必须在头文件中添加宏Q_OBJECT,这样才能被展开,否则信号与槽将无法使用。

 

1.4.总结 

作为一个初级开发者并不需要研究 信号是如何产生的 这种问题,只需要知道:某个对象具有哪些系统提供的信号,以及如何自定义信号;定义好槽函数;使用connect()函数将信号与槽函数连接,就可以使用了。

个人认为,Qt中的信号与槽机制很像51单片机中的中断机制:一个中断被触发,就会执行对应的中断处理函数。

关于可携带参数的信号与槽,暂时不做讲解,以后会进行更新。

PS:本人实属C/C++小白一枚,目前处于找实习的阶段,在复习知识点的过程中会把一些觉得有必要的内容进行总结,一方面为了加深自己的理解和记忆,另一方面也希望能为需要的同学提供帮助。欢迎喜欢C/C++的同学共同交流,提出宝贵意见。谢谢!