QTimer в классе шаблонов

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

Он обрабатывает событие, ища событие в таблице (где состояние и событие совпадают), а затем вызывает указатель на соответствующую функцию.

Это все работает. Далее я хочу добавить таймер, чтобы по истечении времени таймера он вызывал функцию processEvent() с кодом события "TIMER_EXPIRED".

Проблема для меня в том, что классы шаблонов Qt не поддерживаются для слотов/сигналов. Итак, я могу добавить QTimer, но я не могу его подключить или определить/излучать слоты/сигналы.

Моя альтернатива — реализовать таймер в классе, которому принадлежит конечный автомат, и это нормально, но тогда мне придется сделать это для всех классов, использующих класс конечного автомата.

Так что я не совсем уверен, в каком направлении двигаться дальше, есть ли какие-то хитрости, которые я могу использовать, чтобы обойти эту проблему?

Я бы добавил пример кода, но поскольку я не смог реализовать QTimer в классе конечного автомата, потому что я не могу наследовать QObject, пока нет кода для показа :(


person code_fodder    schedule 27.10.2015    source источник
comment
Вы можете использовать лямбды вместо слотов.   -  person Dmitry Sazonov    schedule 27.10.2015
comment
@SaZ, я не на 100% разбираюсь в лямбда-функциях, но я до сих пор не понимаю, как они могут помочь мне реализовать QTimer в моем классе, можете ли вы объяснить, что вы имеете в виду?   -  person code_fodder    schedule 27.10.2015


Ответы (1)


Лямбды можно использовать следующим образом:

#pragma once

#include <QDebug>
#include <QTimer>

template< class T > class MyClass
{
public:
    MyClass()
    {
        _timer.setInterval(1000);
        // connecting the signal to the lambda
        // that will call the desired function:
        QObject::connect(&_timer, &QTimer::timeout,
                &_timer, [&](){
            theFunctionThatNeedToBeRunOnTimer();
        });
        _timer.start();
    }

    void theFunctionThatNeedToBeRunOnTimer()
    {
        qDebug() << "Timer ticked!";
    }

private:
    QTimer _timer;
};
person SingerOfTheFall    schedule 27.10.2015
comment
Спасибо, похоже, это работает (компилируется), но я не совсем понимаю! Как лямбда преобразуется в функцию типа слота? Спасибо : ) - person code_fodder; 27.10.2015
comment
@code_fodder, это не так, этот синтаксис connect был введен специально для случая привязки сигнала к лямбде или функтору. Обратите внимание на третий параметр, который используется в качестве контекста для лямбды. Если объект, переданный в качестве третьего параметра, будет уничтожен, сигнал не будет испущен. Подробнее здесь. - person SingerOfTheFall; 27.10.2015
comment
аааа, понятно, большое спасибо :) .. так что теоретически вы можете проделать тот же трюк только с функтором (и не обязательно с лямбдой? - person code_fodder; 27.10.2015
comment
@code_fodder, да, вы тоже можете использовать функтор, но использование лямбды более лаконично. - person SingerOfTheFall; 27.10.2015
comment
@code_fodder На самом деле вы можете connect использовать любой метод любого класса. Класс, к которому вы подключаетесь, не обязательно должен быть QObject, и даже в QObject его не нужно объявлять как слот. - person Kuba hasn't forgotten Monica; 27.10.2015
comment
@KubaOber ах ... Итак, в примере кода SingerOfTheFall, как бы вы соединили его сигнал timer-›timeout() с функцией, котораяNeedToBeRunOnTimer() без лямбда? Я пробовал это в своем коде и не смог заставить это работать... - person code_fodder; 28.10.2015
comment
@code_fodder connect на std::bind(&Class::method, object). В данном случае connect(&_timer, &QTimer::timeout, std::bind(&MyClass::theFunctionThatNeedToBeRunOnTimer, this)). Не забудьте #include <functional> - person Kuba hasn't forgotten Monica; 28.10.2015
comment
@KubaOber Большое спасибо! - person code_fodder; 29.10.2015