信号/插槽与直接功能调用

时间:2009-07-22 05:41:22

标签: c++ qt

所以我开始学习Qt 4.5并发现Signal / Slot机制有所帮助。但是,现在我发现自己正在考虑两种类型的架构。

这是我要使用的那个

class IDataBlock
{
   public:
   virtual void updateBlock(std::string& someData) = 0;
}

class Updater
{

   private:
    void updateData(IDataBlock &someblock)
    {
         ....
       someblock.updateBlock(data);
          ....
    }
}

注意:内容代码为简洁起见。

现在有信号我可以

void Updater::updateData()
{
    ...
    emit updatedData(data);
}

这更干净,减少了界面的需要,但我应该这样做只是因为我可以吗?第一个代码块需要更多的输入和更多的类,但它显示了一种关系。使用第二块代码,一切都更“无形”。哪一个更可取,如果是逐案的,那么指导原则是什么?

3 个答案:

答案 0 :(得分:9)

发送信号需要花费很少的开关和一些额外的函数调用(取决于连接的内容和方式),但开销应该是最小的。

信号的提供者无法控制其客户是谁,即使他们在发出返回的时间内实际上都获得了信号。

这非常方便并且允许完全解耦,但是当执行顺序很重要或者想要返回某些内容时也会导致问题。

永远不要传递指向临时数据的指针(除非你确切地知道你在做什么,即便如此......)。如果必须,传递成员变量的地址 - Qt提供了一种方法来延迟对象的破坏,直到处理完所有事件后。

信号也可能要求事件循环运行(除非我认为连接是直接的)。

总的来说,它们在事件驱动的应用程序中非常有意义(实际上,如果没有它们,很快就会变得非常烦人)。

如果您已在项目中使用Qt,请务必使用它们。如果对Qt的依赖是不可接受的,那么boost也有类似的机制。

答案 1 :(得分:3)

还有另一个区别。 #1与IDataBlock接口硬连接,Updater类需要知道“someblock”。 #2可以通过连接呼叫(或多个,包括断开连接)进行后期耦合,从而实现更加动态的方法。 #2就像一条消息(想想Smalltalk / ObjC)而不是一个电话(想想C / C ++)。消息也可以进行多次调度,这需要在#1中实现该功能。

我的偏好是利用信号/插槽由于它们的灵活性,除非代码性能或需要立即返回数据不允许它(或者不希望依赖于Qt)。

答案 2 :(得分:2)

这两种形式似乎相似。从功能上讲,这是事实。在实践中,您正在解决一个更大的问题。在这些情况下,外部环境会导致这两种解决方案不相同。

一个常见的情况是找出源和汇之间的关系。他们甚至互相认识吗?在你的第一个例子中,updateData()需要传入接收器。但是如果触发器是GUI按钮[更新数据]怎么办?按钮是通用组件,不应该知道IDataBlock。

解决方案当然是将m_someblock成员添加到Updater。按钮现在将更新Updater中的任何成员。但这真的是你想要的吗?