【问题标题】:Qt: style regarding signals/slotsQt:关于信号/槽的样式
【发布时间】:2011-12-23 16:01:34
【问题描述】:

我有一个对象 X,它拥有(拥有指向并初始化)对象 Y1..10

对象 X 具有不时变化的状态。 我希望子对象 (Y1..10) 能够了解状态。

通常,这可以通过从每个 Y 子对象指向父 X 的指针来解决,以便它可以通过方法调用查询其状态,但我不希望 Y 对象知道对象 X,只是它的状态。

我想知道这是否可以通过信号/插槽来实现:

Y 对象将定义一个信号,例如:

void GetStatus(TheStatus & status);

X 对象将 this 连接到一个插槽,当由 Y 对象发出时,对象 X 会将状态写入给定的状态引用,以便 Y 对象获取它。

这样我可以让 Y 对象的状态更新可用,但是,他们不需要知道对象 X 来实现这一点。

你怎么看?

【问题讨论】:

    标签: qt signals-slots observer-pattern


    【解决方案1】:

    看起来你是在倒退。如果 X 对象是想要进行“通知”的对象,那么它应该发出信号。然后 Y 对象将拥有成为“接收者”的插槽。

    所以 X 对象应该发出一个信号,例如:

    void X::statusChanged(TheStatus status);
    

    那么 Y 对象就会有某种匹配的槽。假设有适当的私有/公共权限,任何对象(可能是 Z 甚至 X 和 Y 本身)都可以使用 QObject::connect 调用将对象实例的匹配信号和槽绑定在一起。您甚至可以将信号与信号联系起来。

    虽然您可以将 Y 中的该插槽称为 onStatusChanged 之类的名称,但这表明您的设计中的耦合有点太紧了。毕竟,插槽可以像常规方法一样被调用。因此,如果您可以考虑插槽的实际作用,而不是根据其调用者来命名它,那会更明智。

    (如果一个函数 foo() 调用另一个函数,我们倾向于根据它的作用给它一个新名称 bar(),而不是 theFunctionCalledByFoo(),对吧?)

    正如 Martin 指出的那样,最好尝试保持插槽使用的类型相当基本并按值发送它们。如果您发送指针和引用,那么您会担心对象的生命周期,尤其是在信号/插槽在队列中处理的多线程场景中。

    一个简单易懂的基于通知的类的一个很好的例子可能是进度条:

    http://developer.qt.nokia.com/doc/qt-4.8/qprogressbar.html#details

    【讨论】:

    • 我使用 doBlah() 作为接收器,它响应按下按钮之类的事件,使用 updateBlah() 来更新 gui 的某些部分
    • @MartinBeckett 进度条有setValue(),但我不知道这比updateValue() 好还是坏。对于更新 GUI 元素的函数,“set”可能听起来有点轻量级,但我可以从两个方面看到它。在任何情况下,它都比onValueChanged() 好——这听起来既像一个信号的名称,又像一个插槽的名称。
    • 您如何称呼它们并不重要。您只需要制定一些约定来将信号/插槽函数直接记在脑海中,因为编译器不会强制执行它。
    • 好吧,根据 Qt 的某人(至少)“命名可能是设计 API 时最重要的一个问题。”也许比我更强有力的声明,但它可以产生很大的不同:doc.qt.nokia.com/qq/qq13-apis.html#theartofnaming
    • 这是真的 - 我仍然必须停下来想想 STL 中的哪一个:empty()/clear()/erase() 或 reserve()/resize() 或 front()/begin()什么。
    【解决方案2】:

    这正是信号/插槽的用途。

    任何数量的孩子都可以订阅信号,而发送代码不需要知道它们,发送者甚至不需要任何接收者来接收它的信号。

    一般来说,我会尽量让信号/插槽发送的值保持简单而不是复杂对象 - 这样更容易单独进行更改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-23
      • 1970-01-01
      • 2012-09-11
      • 2021-02-12
      相关资源
      最近更新 更多