Досить частою проблемою при роботі з сигналами зі слотами 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 ігнорують рівні доступу методів, порушуючи ООП.
Загалом, для мене вже цього достатньо, а для Вас?
Отличная необходимая статья.