Скажем, у меня есть классРазоблачение внутренний компонент класса для того, чтобы предотвратить писать слишком много кода и влияние на производительность
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 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
нити и присоединительных timeout()
сигнала workerTimer
«s к B::slotGetData()
.
Цель этого класса заключается в обеспечении надлежащей интеграции (многопоточный) из 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;
}
Класс ThirdParty
прирост непрямого доступа к конкретным функции от B
до A
.
Теперь дилемма я столкнулся заключается в следующем:
- Должен ли я просто ретранслировать сигнал данных, который поступает из
B
черезA
и выставить его в качестве сигналаA
или - Должен ли я просто вернуться a
const
ссылка наB
, чтобы разрешить класс, в котором естьA
(чтобы он мог использоватьB
) для прямого подключения кB
'ssignalData(int x)
?
В первом случае (который я есть) я в основном должны отражать каждый сигнал B
хочет, чтобы предложить снаружи внутрь A
(путем предоставления соответствующих закрытых слотов в A
, а также сигналы, которые являются в основном такими же, как B
's). Излишне говорить, что это приводит к тому, что у него слишком много одинакового материала, а также имеет некоторое (хотя и незначительное) влияние на производительность, так как я получаю 2 сигнала (от B
до A
, а затем от A
до любого другого объекта A
) и 2 слота (один из A
для получения сигнала от B
и один в зависимости от того, какой другой объект имеет A
, чтобы получить сигнал от A
).
Второй случай кажется хорошим, но я боюсь, что я буду подвергать особенности B
которых класс, содержащий A
не может быть разрешено иметь доступ к
Если второй случай реализуется, я бы что-то вроде этого (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
, но и все его публичные слоты будут выставлены. Если все это должно быть использовано, нет проблем с этой степенью воздействия, но в противном случае ... не так много.
Система сигнальных слотов является одним из средств развязывания классов. Использование его для плотной пары классов, как вы делаете, кажется противоречивым. Вообще говоря, если классы A и B взаимодействуют друг с другом, но могут быть развязаны, отделите их и позвольте своему пользователю составить/связать их по мере необходимости. Разумеется, вы можете иметь вспомогательные функции, которые учитывают общие шаблоны связей между A и B, если вы их повторно используете. В идеале A не должен знать тип B и наоборот, и они должны быть построены изолированно. –
'A' и' B' плотно связаны, за исключением очень ограниченного набора функций. «A» - это единственное, что приносит «B», чтобы жить, и в основном несет ответственность за «ThirdParty», чтобы фактически получить какие-либо данные. Многие из функций 'B' на самом деле не слоты, а просто простые функции, к которым должен обращаться только« A ». – rbaleksandar