У меня проблемы с освоением нового синтаксиса сигнала / слота (с использованием указателя на функцию-член) в Qt 5, как описано в разделе «Синтаксис нового сигнального слота» . Я попытался изменить это:
QObject::connect(spinBox, SIGNAL(valueChanged(int)),
slider, SLOT(setValue(int));
к этому:
QObject::connect(spinBox, &QSpinBox::valueChanged,
slider, &QSlider::setValue);
но я получаю сообщение об ошибке при попытке его скомпилировать:
ошибка: нет соответствующей функции для вызова
QObject::connect(QSpinBox*&, <unresolved overloaded function type>, QSlider*&, void (QAbstractSlider::*)(int))
Я пробовал использовать clang и gcc в Linux, оба с -std=c++11
.
Что я делаю не так, и как я могу это исправить?
Ответы:
Проблема здесь в том, что есть два сигнала с таким именем:
QSpinBox::valueChanged(int)
иQSpinBox::valueChanged(QString)
. Начиная с Qt 5.7, есть вспомогательные функции для выбора желаемой перегрузки, поэтому вы можете написатьДля Qt 5.6 и ранее вам нужно указать Qt, какой из них вы хотите выбрать, приведя его к правильному типу:
Я знаю, это некрасиво . Но выхода нет. Сегодняшний урок: не перегружайте свои сигналы и слоты!
Приложение : что действительно раздражает в актерском составе, так это то, что
void
(для сигналов).Итак, я обнаружил, что иногда использую этот фрагмент кода C ++ 11:
Использование:
Я лично считаю это не очень полезным. Я ожидаю, что эта проблема исчезнет сама собой, когда Creator (или ваша IDE) автоматически вставит правильное приведение при автозавершении операции взятия PMF. А пока ...
Примечание: синтаксис подключения на основе PMF не требует C ++ 11 !
Приложение 2 : в Qt 5.7 для смягчения этого были добавлены вспомогательные функции, смоделированные после моего обходного пути выше. Главный помощник
qOverload
(у вас тоже естьqConstOverload
иqNonConstOverload
).Пример использования (из документации):
Приложение 3 : если вы посмотрите документацию по любому перегруженному сигналу, теперь решение проблемы перегрузки четко указано в самих документах. Например, https://doc.qt.io/qt-5/qspinbox.html#valueChanged-1 говорит
источник
static_cast
уродство старому синтаксису просто потому, что новый синтаксис позволяет проверять во время компиляции наличие сигнала / слота, когда старый синтаксис не работает во время выполнения.QSerialPort
)Сообщение об ошибке:
Важной частью этого является упоминание « неразрешенного типа перегруженной функции ». Компилятор не знает, имеете в виду
QSpinBox::valueChanged(int)
илиQSpinBox::valueChanged(QString)
.Есть несколько способов устранить перегрузку:
Укажите подходящий параметр шаблона для
connect()
Это заставляет
connect()
разрешить&QSpinBox::valueChanged
перегрузку, которая требуетint
.Если у вас есть неразрешенные перегрузки для аргумента слота, вам необходимо указать второй аргумент шаблона
connect()
. К сожалению, нет синтаксиса, чтобы запросить вывод первого, поэтому вам нужно будет указать оба. Вот когда может помочь второй подход:Используйте временную переменную правильного типа
Назначение для
signal
выберет желаемую перегрузку, и теперь ее можно успешно подставить в шаблон. Это одинаково хорошо работает с аргументом «слот», и в этом случае я считаю его менее громоздким.Использовать преобразование
Здесь можно избежать
static_cast
, поскольку это просто принуждение, а не снятие языковых защит. Я использую что-то вроде:Это позволяет нам писать
источник
На самом деле, вы можете просто обернуть свой слот лямбдой и вот так:
будет лучше. : \
источник
Приведенные выше решения работают, но я решил это немного по-другому, используя макрос, так что на всякий случай вот он:
Добавьте это в свой код.
Затем ваш пример:
становится:
источник
#define CONNECTCAST(class,fun,args) static_cast<void(class::*)args>(&class::fun)
использовать какCONNECTCAST(QSpinBox, valueChanged, (double))
в данном случае.