说实话,Qt给我的感觉像一种魔改版c++,不纯粹,看不到内部的源代码,也不知道一些宏是怎么实现的...
信号与槽内部机制
回归正题,其实学过设计模式的应该都能看出来,qt的这个机制是一个观察者模式;
要实现一个观察者模式最简单的方法就是在信号函数里直接掉用槽机制,发送信号就是调用信号函数,在高级一点,为了拜托信号函数与槽函数的紧耦合,我们可以用函数指针将其解耦;
信号与槽的创建
-:信号与槽的创建都需要类去继承QObject
-:信号需要在定义信号函数前加signals:,其默认是public,不能在其前加上访问权限符号
-:槽需要在其前加上public/private/protected slots: ,与信号创建不同的是其需要在前面加上访问权限符号
-:信号函数只能是声明,不能有定义,定义会自动由moc实现;
-:信号函数返回值只能是void
-:槽函数需要有定义;
-:当发送信号且向其传参时,会将参数按照规则传递给槽函数
信号与槽的关系的创建
-:如果要将信号和槽之间建立联系需要满足以下条件
·:信号与槽的参数类型要从左到右一一对应
·:信号的参数要>=槽参数的个数,信号的参数传递给槽时,从左到右对应,多余的参数会忽 略
-:建立方式:
-:连接信号和槽需要注意:
·:形式1的SINGAL和SLOT宏只是把其中的内容转换为const char*,所以字符串的内容必须与实际函数意义相同,所以并不能用typedef的类型,虽然他们代表的类相同
·:由于形式3用的是模板函数,所以并不依赖与上述两个宏,自然也没那么多约束,但两者都有各自的优点和缺点
·:形式1无论槽是什么访问权限,都能使用,但是因为形式3的语法限制,只能是public
·:因为语法限制,当槽中的函数被重载时,形式1会有二义性,这个时候我们可以用static_cast<>来解决:
测试代码:
#pragma once
#include<qobject.h>
#include<qdebug.h>
class sender :public QObject {
Q_OBJECT
signals:
void m_sign(int num);
public:
explicit sender(QObject* parent = nullptr) {}
~sender() {}
};
class receiver : public QObject {
Q_OBJECT
public slots:
void m_slot(int num) {
qDebug() << "receiver " << num;
}
void m_slot() {
qDebug() << "receiver ";
}
};
sender se;
receiver re;
int main(int argc, char *argv[])
{
QObject::connect(&se, &sender::m_sign, &re, static_cast<void(receiver::*)(int)>(&receiver::m_slot));
emit se.m_sign(1);
}