暴露 class 的内部组件,以防止编写过多代码和影响性能

Exposing internal component of a class in order to prevent writing too much code and impact on performance

假设我有一个 class

class B : public class QObject {
  Q_OBJECT
public:
  B(QObject* parent=Q_NULLPTR);
signals:
   void signalData(int data);
public slots:
  void slotGetData();
private:
}

slotGetData() 是外部触发的,基本上是从某处检索一些数据,然后使用 signalData(int data) 将其发回。另一方面,我还有另一个 class

class A : public class QObject {
  Q_OBJECT
public:
  A(QObject* parent=Q_NULLPTR) {
    // Init B, move to thread, setup timer, connect timer's timeout to B's slotGetData()

    // Connect B to A
    connect(this->B, SIGNAL(signalData(int)), this, SLOT(slotGetData(int)));
  }
signals:
  // Emit signal containing data to another Qt component
  void signalData(int x);
private slots:
  // Connect B::signalData(int x) to this slot and re-emit the data using A::signalData(int x). Don't do anything with the data!
  void slotGetData(int x);
private:
  B* workerObj;
  QThread worker;
  QTimer workerTimer;
}

主要负责实例化 workerObj,将其移动到 worker 线程并将 workerTimertimeout() 信号连接到 B::slotGetData()

此 class 的目的是在想要使用它的第三方 class 中启用 B 的正确集成(多线程),例如:

class ThirdParty : public class QWidget {
  Q_OBJECT
public:
  ThirdParty(QObject* parent=Q_NULLPTR) {
    // Init A

    // Connect to B through A
    connect(this->integrationObj, SIGNAL(signalData(int)), this, SLOT(slotGetData(int)));
  }
private slots:
  // Connect A::signalData(int x) to this slot and do something with the x (change UI, whatever)
  void slotGetData(int x);
private:
  A* integrationObj;
}

class ThirdParty 通过 A.

间接访问 B 的特定功能

现在我面临的困境是:

在第一种情况下(我有)我基本上必须镜像每个信号 B 想要在 A 内向外部提供(通过在 [=25] 中提供相应的专用插槽=] 以及与 B 基本相同的信号)。不用说,这会导致有太多相同的东西,并且还会产生一些(即使只是轻微的)性能影响,因为我得到 2 个信号发射(从 BA 然后从 A 到具有 A 的任何其他对象)和 2 个插槽调用(一个在 A 中以从 B 获取信号,另一个在具有 A 的其他对象中从中获取信号A).

第二种情况看起来不错,但我担心我会暴露 B 的特性,其中包含 A 的 class 可能不允许访问

如果实现第二种情况,我会得到这样的结果(B 不变):

class A : public class QObject {
  Q_OBJECT
public:
  A(QObject* parent=Q_NULLPTR);
  const B* getB() const; // Return a reference to B that cannot be changed but can be used to expose B's slots and signals
signals:
private slots:
private:
  B* workerObj;
  QThread worker;
  QTimer workerTimer;
}

class ThirdParty : public class QWidget {
  Q_OBJECT
public:
  ThirdParty(QObject* parent=Q_NULLPTR) {
    // Init A

    // Connect to B directly!
    connect(this->A->getB(), SIGNAL(signalData(int)), this, SLOT(slotGetData(int)));
  }
private slots:
  // Connect B::signalData(int x) to this slot and do something with the x (change UI, whatever)
  void slotGetData(int x);
private:
  A* integrationObj;
}

我应该在这里做什么?遗憾的是,没有 私有信号 因此所有 B 信号及其所有 public 插槽都将暴露。如果这些都要用到,这个曝光度没有问题,但除此之外……没那么多。

facepalm 我已经在我的另一个项目中找到了解决方案。 :D 我只需要在 A 内提供一个 connectTo(QObject* thirdparty),它在内部仅将 thirdparty 插槽连接到 B 的特定信号,因此不会暴露来自 B 的东西不应该暴露!

另一个更好的解决方案是使用 signal-to-signal 连接 (connect(const QObject *sender, const char *signal, const char *method, Qt::ConnectionType type)) 或使用 child-parent 关系,尽管在后者中我必须确保确实设置了父级。这也称为信号转发,需要 2 个信号但不需要额外的插槽。由于 AThirdParty 可见,我可以做(this 这里代表 ThirdPartyconnect(this, SIGNAL(signalFromThirdPartyToB()), this->a, SIGNAL(signalFromAToB()))ThirdParty 信号的转发设置为 B 通过 A,然后通过调用 A 中的转发信号与 B 中的插槽之间的实际 signal-slot 连接(this 这里表示 A) connect(this, SIGNAL(signalFromAToB()), this->b, SLOT(slotB())).