Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 什么是信号和插槽?_C++_Design Patterns_Signals Slots - Fatal编程技术网

C++ 什么是信号和插槽?

C++ 什么是信号和插槽?,c++,design-patterns,signals-slots,C++,Design Patterns,Signals Slots,有人能简单地解释一下“信号和插槽”模式吗?信号和插槽是一种将发送方(信号)和零个或多个接收方(插槽)解耦的方法。假设您是一个系统,其中包含您希望使系统中对这些事件感兴趣的任何其他部分都可用的事件。与其将生成事件的代码硬连接到希望了解这些事件的代码,不如使用信号和插槽模式 当发送方发出事件信号(通常通过调用与该事件/信号相关联的函数)时,该事件的所有接收方将自动被调用。这允许您在程序生命周期内根据需要连接和断开接收器 因为这个问题被标记为C++,这里有一个更为彻底的解释的链接。 < P>我假设你在

有人能简单地解释一下“信号和插槽”模式吗?

信号和插槽是一种将发送方(信号)和零个或多个接收方(插槽)解耦的方法。假设您是一个系统,其中包含您希望使系统中对这些事件感兴趣的任何其他部分都可用的事件。与其将生成事件的代码硬连接到希望了解这些事件的代码,不如使用信号和插槽模式

当发送方发出事件信号(通常通过调用与该事件/信号相关联的函数)时,该事件的所有接收方将自动被调用。这允许您在程序生命周期内根据需要连接和断开接收器


因为这个问题被标记为C++,这里有一个更为彻底的解释的链接。

< P>我假设你在谈论QT的信号和时隙。 这很简单

一个类的实例可以触发一个信号,而另一个类的另一个实例可能可以在插槽中捕获该信号。这有点像函数调用,只是调用函数的人不需要知道谁想要接收调用

最好用一个例子来说明。
类QPushButton有一个信号QPushButton::clicked()。只要点击按钮,就会触发该信号。按钮不需要知道谁有兴趣知道发生了单击。它只是触发信号,感兴趣的人都可以连接到它。
按钮所在的QDialog实际上很想知道按钮是何时单击的。它具有插槽MyDialog::buttonClicked()。在MyDialog c'tor上,您需要将()按钮单击()信号连接到对话框的buttonClicked()插槽,以便在触发信号时调用该插槽

一堆更高级的东西:

  • 参数,信号可以有参数,这些参数也可以选择性地传递到插槽
  • 跨线程调用-如果您正在进行需要跨线程的信号插槽连接,那么QT将自动缓冲信号并将其排队到正确的线程。例如,当GUI线程需要与工作线程通信时,这种情况会自动发生

我认为,当您将信号和插槽视为可能的应用工具时,可以最好地描述它们。有一个
信号
,例如发布服务器端的
按钮按下(IdType)
。无论何时按下按钮,都会调用连接到该信号的所有插槽。插槽位于用户端。例如,插槽可以是
sendMail(IdType)

随着“按钮按下”事件的发生,插槽将知道按下了哪个按钮,因为id将被移交
IdType
表示通过发布服务器和订阅服务器之间的连接发送的数据类型。订户可能的操作是
connect(信号,插槽)
,它可以将
按钮按下(IdType)
sendMail(IdType)
连接起来,这样,如果按下按钮,就会调用特定的插槽

这样做的好处是订户(插槽侧)不需要关心信号的细节。它只需要连接。因此,这里有大量的松耦合。您可以更改按钮的实现,但是插槽的接口仍然是相同的


查看或获取更多信息。

想象一下应用程序中有一个GUI。大多数情况下,控制流不是很线性的,也就是说,如果没有一个清晰的操作序列,您将有一个与GUI交互的用户(如按钮、菜单等)

这本质上是一个事件驱动的模型,可以通过信号和插槽模式很好地实现。信号是由对象(比如GUI组件)生成的事件,插槽是这些事件的接收器

下面是一个例子:假设您有一个复选框,在您的编程语言中表示为一个对象。该复选框可能会发生多种情况:它可以切换,这也意味着它可以设置或取消设置。这些是它能发出的信号。我们将它们命名为checkboxToggled、checkboxSet和checkboxUnset。如您所见,在本例中,复选框在切换时始终会发出checkboxToggled信号,但也会发出另外两个信号中的一个,具体取决于状态的变化

现在想象一下有一些其他对象,即标签,在本例中,标签始终作为对象存在,但可以“出现”和“消失”,系统发出嘟嘟声(也由对象表示),它可以简单地发出嘟嘟声。这些是这些对象拥有的插槽。我们将它们称为“message出现”、“message消失”和“beep”

假设您希望每次切换复选框时系统发出嘟嘟声,并且根据用户是否选中或清除复选框,标签显示或消失

因此,您可以将以下信号连接到以下插槽(左侧为信号,右侧为插槽):

基本上就是这样

信号和插槽也可能有参数。例如,使用设置数值的滑块,您希望在用户移动滑块时立即发送更改的值和发出的信号:sliderChanged(int)

当然,要真正做一些有用的事情,您需要编写一些自己的类,其中包含一些自己的信号和插槽。这是很容易做到的,使用这些自己的信号和插槽,您可以很好地以事件驱动的方式与GUI或代码的其他部分进行交互

请记住,信号和插槽通常是对称的,因为通常可能存在与插槽对应的信号。例如,复选框在切换时可能会发出信号,但也可能包含切换chec的插槽
checkboxToggled -> beep
checkboxSet -> messageAppear
checkboxUnset -> messageDisappear