Вызов функции в производном классе из базового класса

#c #linux

Вопрос:

У меня есть класс таймера, в котором по истечении времени будет вызываться TimeEventHdlr. Если предусмотрена функция обратного вызова, то она вызовет ту, которая еще вызовет функцию внутри класса. Каким было бы лучшее решение для вызова функции производного класса по истечении таймера?

 typedef void(*TimerCallback)();

struct Parm {
    TimerCallback clbk;
};

class TimerHdlr {
    TimerHdlr(Parm amp;parm);
    timer_t mTimerId;
    TimerCallback mTimerClbk;
    void StartTimer();
    void TimerFunc();
    static void TimeEventHdlr(sigval_t sigVal);
};

TimerHdlr::TimerHdlr(Parm amp;parm) : mTimerClbk(parm.clbk) {
    struct sigevent sigev;
    memset(amp;sigev, 0, sizeof(struct sigevent));
    sigev.sigev_value.sival_ptr = (void *)this;
    sigev.sigev_notify = SIGEV_THREAD;
    sigev.sigev_notify_function = amp;TimerHdlr::TimeEventHdlr;
    timer_create(CLOCK_REALTIME, amp;sigev, amp;mTimerId);
}

void TimerHdlr::StartTimer() {
    struct itimerspec timerSpec;
    timerSpec.it_interval.tv_sec = 0; /* oneshot timer */
    timerSpec.it_interval.tv_nsec = 0;
    timerSpec.it_value.tv_sec = 10;
    timerSpec.it_value.tv_nsec = 0;
    timer_settime(mTimerId, 0, amp;timerSpec, NULL);
}

void TimerHdlr::TimerFunc() {}

/*static*/ void TimerHdlr::TimeEventHdlr(sigval_t val) {
    TimerHdlr *obj = static_cast<TimerHdlr*>(val.sival_ptr);
    if (obj->mTimerClbk == nullptr)
        obj->TimerFunc();
    else
        obj->mTimerClbk();
}
 

Реализация производного класса:

 class DerivedTimer: public TimerHdlr {
    static void TimeoutClbkHdlr(); 
};

Parm parm = {.clbk = DerivedTimer::TimeoutClbkHdlr};

DerivedTimer::DerivedTimer() : TimerHdlr(parm) {
}

/*static*/ void DerivedTimer::TimeoutClbkHdlr() {
// function to called when base timer elapses
}
 

Комментарии:

1. Знаете ли вы о виртуальных функциях ?

Ответ №1:

Заставьте TimerFunc() быть virtual внутри TimerHdlr , а затем переопределите его DerivedTimer . Нет необходимости в статическом TimeoutClbkHdlr методе DerivedTimer .

 typedef void(*TimerCallback)();

class TimerHdlr {
private:
    timer_t mTimerId;
    TimerCallback mTimerClbk;
    static void TimeEventHdlr(sigval_t sigVal);
protected:
    virtual void TimerFunc();
public:
    TimerHdlr(TimerCallback clbk = nullptr);
    void StartTimer();
};

TimerHdlr::TimerHdlr(TimerCallback clbk) : mTimerClbk(clbk) {
    struct sigevent sigev;
    memset(amp;sigev, 0, sizeof(struct sigevent));
    sigev.sigev_value.sival_ptr = (void *)this;
    sigev.sigev_notify = SIGEV_THREAD;
    sigev.sigev_notify_function = amp;TimerHdlr::TimeEventHdlr;
    timer_create(CLOCK_REALTIME, amp;sigev, amp;mTimerId);
}

void TimerHdlr::StartTimer() {
    struct itimerspec timerSpec;
    timerSpec.it_interval.tv_sec = 0; /* oneshot timer */
    timerSpec.it_interval.tv_nsec = 0;
    timerSpec.it_value.tv_sec = 10;
    timerSpec.it_value.tv_nsec = 0;
    timer_settime(mTimerId, 0, amp;timerSpec, NULL);
}

void TimerHdlr::TimerFunc() {}

/*static*/ void TimerHdlr::TimeEventHdlr(sigval_t val) {
    TimerHdlr *obj = static_cast<TimerHdlr*>(val.sival_ptr);
    if (obj->mTimerClbk == nullptr)
        obj->TimerFunc();
    else
        obj->mTimerClbk();
}
 
 class DerivedTimer: public TimerHdlr {
protected:
    void TimerFunc() override;
public:
    DerivedTimer();
};

DerivedTimer::DerivedTimer() : TimerHdlr() {
}

void DerivedTimer::TimerFunc() {
    // function to called when base timer elapses
}