Довольно частой проблемой при работе с сигналами с слотами в Qt5 по моим наблюдениям за вопросами на форуме является подключение слотов в рамках синтаксиса на указателях к сигналам имеющим перегрузку сигнатуры. Тоже самое касается и слотов, которые имеют перегрузку.
Возьмём тестовый класс, который имеет перегруженные сигналы.
#include <QObject> class TestClass : public QObject { Q_OBJECT public: explicit TestClass(QObject *parent = nullptr); signals: void testSignal(int arg1); void testSignal(int arg1, int arg2); };
Здесь имеется сигнал, с перегрузкой сигнатуры. Подключаться данный сигнал также будет к слотам, которые объявлены в классе Widget , и которые также имеют перегрузку сигнатуры.
#include <QWidget> #include "testclass.h" namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void onTestSlot(int arg1); void onTestSlot(int arg1, int arg2); private: Ui::Widget *ui; TestClass* m_testClass; };
Как было в Qt4
В рамках Qt4 всё решалось довольно просто, указанием сигнатуры сигнала и слота в макросах SIGNAL и SLOT.
connect(m_testClass, SIGNAL(testSignal(int,int)), this, SLOT(onTestSlot(int,int))); connect(m_testClass, SIGNAL(testSignal(int)), this, SLOT(onTestSlot(int)));
Как стало в Qt5
А вот в Qt5 при записи в новом синтаксисе сигналов и слотов имеются некоторые проблемы. Поскольку потребуется делать static_cast сигнатуры метода.
connect(m_testClass, static_cast<void(TestClass::*)(int)>(&TestClass::testSignal), this, static_cast<void(Widget::*)(int)>(&Widget::onTestSlot)); connect(m_testClass, static_cast<void(TestClass::*)(int, int)>(&TestClass::testSignal), this, static_cast<void(Widget::*)(int, int)>(&Widget::onTestSlot));
К слову говоря, новый синтаксис также позволяет подключать сигналы к слотам с меньшей сигнатурой, как это было в Qt4.
connect(m_testClass, static_cast<void(TestClass::*)(int, int)>(&TestClass::testSignal), this, static_cast<void(Widget::*)(int)>(&Widget::onTestSlot));
Плюсы нового синтаксиса
А теперь камень преткновения. Зачем использовать новый синтаксис сигналов и слотов? Этот вопрос до сих пор периодически слышу. Особенно, когда люди видят такие страшные касты сигнатур.
Поэтому перечислю потенциальные плюсы:
- Возможность отслеживания ошибок в подключении сигналов и слотов ещё на этапе компиляции, а не в рантайме
- Уменьшение затрат времени компиляции за счёт исключения макросов из кода
- Возможность подключения лямбда функций, это довольно важная плюшка
- Ограждаем себя от ошибок, когда пытаемся подключиться извне к приватному слоту. Да!! Да!! Макросы SIGNAL и SLOT игнорируют уровни доступа методов, нарушая ООП.
В общем-то для меня уже этого достаточно, а для Вас?
Отличная необходимая статья.