暴露 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
线程并将 workerTimer
的 timeout()
信号连接到 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
的特定功能
现在我面临的困境是:
- 我是否应该通过
A
中继来自 B
的数据信号并将其公开为 A
或 的信号
- 我是否应该 return 对
B
的 const
引用以允许其中包含 A
的 class(以便它可以使用 B
) 直接连接到 B
的 signalData(int x)
?
在第一种情况下(我有)我基本上必须镜像每个信号 B
想要在 A
内向外部提供(通过在 [=25] 中提供相应的专用插槽=] 以及与 B
基本相同的信号)。不用说,这会导致有太多相同的东西,并且还会产生一些(即使只是轻微的)性能影响,因为我得到 2 个信号发射(从 B
到 A
然后从 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 个信号但不需要额外的插槽。由于 A
对 ThirdParty
可见,我可以做(this
这里代表 ThirdParty
) connect(this, SIGNAL(signalFromThirdPartyToB()), this->a, SIGNAL(signalFromAToB()))
将 ThirdParty
信号的转发设置为 B
通过 A
,然后通过调用 A
中的转发信号与 B
中的插槽之间的实际 signal-slot 连接(this
这里表示 A
) connect(this, SIGNAL(signalFromAToB()), this->b, SLOT(slotB()))
.
假设我有一个 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
线程并将 workerTimer
的 timeout()
信号连接到 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
的特定功能
现在我面临的困境是:
- 我是否应该通过
A
中继来自B
的数据信号并将其公开为A
或 的信号
- 我是否应该 return 对
B
的const
引用以允许其中包含A
的 class(以便它可以使用B
) 直接连接到B
的signalData(int x)
?
在第一种情况下(我有)我基本上必须镜像每个信号 B
想要在 A
内向外部提供(通过在 [=25] 中提供相应的专用插槽=] 以及与 B
基本相同的信号)。不用说,这会导致有太多相同的东西,并且还会产生一些(即使只是轻微的)性能影响,因为我得到 2 个信号发射(从 B
到 A
然后从 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 个信号但不需要额外的插槽。由于 A
对 ThirdParty
可见,我可以做(this
这里代表 ThirdParty
) connect(this, SIGNAL(signalFromThirdPartyToB()), this->a, SIGNAL(signalFromAToB()))
将 ThirdParty
信号的转发设置为 B
通过 A
,然后通过调用 A
中的转发信号与 B
中的插槽之间的实际 signal-slot 连接(this
这里表示 A
) connect(this, SIGNAL(signalFromAToB()), this->b, SLOT(slotB()))
.