【问题标题】:Qt Forwarding signal/slot connectionsQt 转发信号/插槽连接
【发布时间】:2016-11-10 03:43:03
【问题描述】:

假设SomeClass 有成员Object1Object2,并且Object1Object2 之间存在联系,例如:

connect(Object1, signal1, Object2, slot1)

经过一些重构,Object3 被添加到SomeClass 并且Object2 被移动为Object3 的成员,但仍然需要Object1Object2 之间的连接。

Object1Object2 之间的通信现在必须通过Object3。这意味着需要修改Object3,添加一对信号/插槽只是为了实现Object1Object2 之间的通信。

这意味着 Object3 的 .h 和 .cpp 都将被修改,添加多行代码来完成以前只需一行完成的事情。

我懒惰的一面告诉我这个故事有一些奇怪的地方。有什么方法可以让这种联系更直接吗?

【问题讨论】:

  • "这意味着 Object3 需要修改..." - 为什么???相同的connect(Object1, signal1, Object2, slot1) 将像以前一样工作(我想Object1Object2 是您代码中的指针)

标签: c++ qt c++11 qt5 c++14


【解决方案1】:

您将Object2 封装在Object3 中。从Object3用户 的角度来看,没有任何改变:仍然只有一行代码来建立连接。 Object3 需要一个额外的插槽来转发到它现在封装的 Object2 实例。这是这里的一个额外行。就是这样。

struct Object1 : QObject {
  Q_SIGNAL void signal1();
  Q_OBJECT
};
struct Object2 : QObject {
  Q_SLOT void slot1() {}
  Q_OBJECT
};
class Object3 : QObject {
  Q_OBJECT
  Object2 m_object2;
public:
  // one line to expose object2's slot
  Q_SLOT void slot1() { m_object2.slot1(); }
};

class SomeClass {
  Object1 m_object1;
  Object3 m_object2;
public:
  SomeClass() {
    // still one line
    connect(&m_object1, &Object1::signal1, &m_object3, &Object3::slot1);
  }
};

【讨论】:

  • 我应该更喜欢 Q_SLOT/Q_SLOTS(和 Q-SIGNAL/Q_SIGNALS、EMIT ...)而不是经典的公共插槽吗?我理解为什么doc.qt.io/qt-5/… 需要它们,但即使不使用 3rd Party Signals and Slots,也应该将其用作默认样式?
  • @KcFnMi 我更喜欢Q_ 前缀,这样全局命名空间就不会被signalsslots 等宏污染。我更喜欢Q_SIGNALQ_SLOT 而不是Q_SIGNALSQ_SLOTS,当信号/插槽的数量很少并且不能保证整个部分时。此外,从逻辑上讲,信号/插槽通常不属于一起,而是与其他方法一起属于。我喜欢使用emit 而不是Q_EMIT,因为它使代码以一种不难看的方式自记录。无论如何,emit/Q_EMIT 的使用是可选的,它仅供人类使用。
  • 以这种方式调用插槽是否仍然是异步的(Q_SLOT void slot1() { m_object2.slot1(); })?
  • @KcFnMi 不可能——这是直接的 C++ 方法调用。当您直接调用事物时,插槽指定不起作用。但是当然,如​​果Object3::slot1 被异步调用,那么m_object2::slot1 也将在object3 的线程上下文中。重要的是,m_object2Object3 在同一个线程中。如果不是,Object3 将不得不通过QMetaObject::invokeMethodother mechanisms 实现异步调用。
猜你喜欢
  • 2012-10-15
  • 1970-01-01
  • 2015-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多