当我遇到以下这段代码时,我正在阅读Qt
教程here:
#include <QObject>
class Counter : public QObject
{
Q_OBJECT
public:
Counter() { m_value = 0; }
int value() const { return m_value; }
public slots:
void setValue(int value);
signals:
void valueChanged(int newValue);
private:
int m_value;
};
有人可以向我解释声明中public slots
,signals
的用法是什么吗?我虽然只有两个,public
和private
。他们叫什么,他们的用途是什么?
答案 0 :(得分:3)
解释不错信号和插槽是Qt中引入的语言结构 对象[1]之间的通信使其易于实现 观察者模式,同时避免样板代码。这个概念就是这样 GUI小部件可以发送包含事件信息的信号 其他控件使用称为插槽的特殊功能接收。
信号/插槽系统非常适合图形用户的方式 接口设计。类似地,可以使用信号/时隙系统 用于其他非GUI用法,例如异步I / O(包括 插座,管道,串行设备等)事件通知或 将超时事件与适当的对象实例和方法相关联 或功能。它易于使用,没有 需要编写注册/注销/调用代码, 因为Qt的元对象编译器(MOC)自动生成 需要的基础设施。
常用的比喻是电子表格。电子表格包含单元格 观察源细胞。当源单元改变时, 依赖单元格从事件中更新。
由于Qt基本上发明了这个概念,你最好真正阅读你在问题中发表的文章。
特别是:
信号
当内部状态发生变化时,对象会发出信号 以某种方式可能对对象的客户或所有者感兴趣。 只有定义信号的类及其子类才能发出 信号。
发出信号时,通常会连接到它的插槽 立即执行,就像正常的函数调用一样。当这个 发生时,信号和插槽机制完全独立于任何 GUI事件循环。执行emit语句后面的代码 所有插槽返回后都会发生。情况略有不同 使用排队连接时有所不同;在这种情况下,代码 跟随emit关键字将立即继续,并插槽 将在稍后执行。
如果有多个插槽连接到一个信号,则插槽将是 按照他们连接的顺序依次执行, 当信号发出时。
信号由moc自动生成,不得为 在.cpp文件中实现。他们永远不会有退货类型(即 使用void)。
关于论点的说明:我们的经验表明信号和插槽 如果他们不使用特殊类型,则更可重复使用。如果 QScrollBar :: valueChanged()是使用特殊类型的 假设的QScrollBar :: Range,它只能连接到插槽 专为QScrollBar设计。连接不同的输入 小部件在一起是不可能的。
和
槽
当发射连接到它的信号时,调用一个插槽。插槽是 普通的C ++函数,可以正常调用;他们唯一特别的 功能是信号可以连接到它们。
由于插槽是普通的成员函数,因此它们遵循普通的C ++ 直接调用时的规则。但是,作为插槽,可以调用它们 任何组件,无论其访问级别如何,都通过信号槽 连接。这意味着从一个实例发出的信号 任意类可以导致在实例中调用私有槽 一个无关的班级。
您还可以将插槽定义为虚拟插槽,我们已经找到了 在实践中很有用。
与回调相比,信号和插槽稍慢,因为 他们提供的灵活性增加了,尽管差别很大 实际应用是微不足道的。一般来说,发出一个信号 连接到一些插槽,大约慢十倍 使用非虚函数调用直接调用接收器。这个 是安全地定位连接对象所需的开销 迭代所有连接(即检查后续接收器) 在发射期间没有被摧毁),并且任何一个都可以 参数以通用方式。十个非虚函数调用 可能听起来很多,它比任何新的或删除都要少得多 例如,操作。一旦你执行字符串,矢量或 列表操作后面的场景需要新建或删除, 信号和插槽开销只对非常小的负责 完整的函数调用成本的比例。
每当您在插槽中进行系统调用时都是如此;要么 间接调用十多个函数。在i586-500上,你可以发射 每秒大约2,000,000个信号连接到一个接收器,或 每秒约1,200,000连接到两个接收器。简单 信号和插槽机制的灵活性非常值得 开销,您的用户甚至不会注意到。
请注意,定义称为信号或变量的变量的其他库 在与a一起编译时,插槽可能会导致编译器警告和错误 基于Qt的应用程序。要解决这个问题,请#undef得罪 预处理器符号。