Как заставить Qt Signal излучать по значению без ошибок компиляции вместо ссылки? - PullRequest
0 голосов
/ 22 ноября 2018

Я прочитал, что концепция сигнал / слот в qt должна всегда передавать аргументы по значению вместо ссылки, чтобы гарантировать, что сигналы / слоты работают безупречно между потоками.

Теперь у меня есть фрагмент кода, который будет компилироватьсякогда аргумент для сигнала передается по ссылке, а не по значению:

#include <QObject>

class mythirdclass {
public:
    mythirdclass();
};

class mysecondclass : public QObject, public mythirdclass {
public:
    mysecondclass(mythirdclass third);
};

class myclass : public QObject {
    Q_OBJECT
public:
    myclass();

signals:
    // not working
    void messageReceived(mysecondclass mymessage);
    // working
    // void messageReceived(mysecondclass &mymessage);
};

myclass::myclass()
{
    mythirdclass third;
    mysecondclass msg(third);
    emit messageReceived(msg);

}

mysecondclass::mysecondclass(mythirdclass third)
{
    // DO stuff
}

mythirdclass::mythirdclass()
{
}

Ошибка компилятора:

..\example\main.cpp: In constructor 'myclass::myclass()':
..\example\main.cpp:28:20: error: use of deleted function 'mysecondclass::mysecondclass(const mysecondclass&)'
  emit signal(second);
                    ^
..\example\main.cpp:8:7: note: 'mysecondclass::mysecondclass(const mysecondclass&)' is implicitly deleted because the default definition would be ill-formed:
 class mysecondclass : QObject, public mythirdclass {
       ^

На основании ошибок, которые я думал о написании конструктора копирования для mysecondclass, однако после некоторых попыток я отказался на данный момент, потому что я не понял это правильно.

Итак, мои вопросы:

  • , почему компиляция завершается неудачно в первойplace?
  • если произойдет сбой из-за отсутствующего конструктора копии, почему компилятор не может определить его неявно?
  • как будет выглядеть конструктор рабочей копии в моем случае?

Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 22 ноября 2018

Почему компиляция не удалась?

Поскольку передача по значению подразумевает копирование, а если конструктор копирования удален, то он просто не может пройти по значениюи ваша функция не может быть скомпилирована с этой подписью, в то время как она может получить свой аргумент по ссылке, потому что она не включает в себя копирование.

Если происходит сбой из-за отсутствующего конструктора копирования, почему компилятор нев состоянии определить одно неявно?

Это на самом деле терпит неудачу, потому что он не смог определить неявно.Причина в том, что ваш класс происходит от QObject.И что QObject не имеет открытого или защищенного конструктора копирования , по замыслу.Таким образом, компилятор не может определить одно неявно.

Как будет выглядеть конструктор рабочей копии в моем случае?

Учитывая природу QObject s и дизайнРешение, которое стоит за этим, когда дело доходит до того, что QObject не подлежит копированию, я бы рекомендовал не использовать сигналы и слоты, которые принимают QObject с или класс, производный от него по значению (или просто любую функцию, которая делает это, и сигналы / слотыв основном функции в глубине), но вместо этого по ссылке или по указателю.

0 голосов
/ 22 ноября 2018

Для вашего третьего вопроса: если вы не хотите определять конструктор по умолчанию для mysecondclass, ваш конструктор копирования, вероятно, будет выглядеть так:

 mysecondclass(mysecondclass const &other) : mythirdclass() {
    /// stuff
 }

Для вашего второго вопроса, я полагаю (не уверен), чтоконструктор копирования по умолчанию пытается использовать конструктор по умолчанию, который был автоматически удален, потому что вы определили другой конструктор mysecondclass из объекта mythirdclass (я бы порекомендовал вам использовать ссылку const для параметра здесь, чтобы избежать бесполезного копирования)

...