2016-03-07 2 views
0

Я пишу свой собственный таймер в C++. Мне было интересно, можно ли передать функцию в конструктор таймера и вызвать эту функцию позже.C++ нестатический указатель функции внутри собственного класса

Я думал об использовании указателей функций для этого, однако я не могу найти решение для передачи нестатической функции внутри самого класса.

G ++ дает мне эту ошибку:

Server.cpp:61:54: error: invalid use of non-static member function serverTimer = new timer::Timer(onTimerTick,3000);

Мой класс server.cpp выглядит следующим образом:

private: 
    void onTimerTick(){ 
      //do something with class variables, so can't use static? :(
     } 
     public: 
     Server(int port) : socket(port) 
     { 
      serverTimer = new timer::Timer(onTimerTick,1000); 
      serverTimer->start(); 
     } 

Это timer.h:

#ifndef TIMER_H 
#define TIMER_H 
namespace timer { 
    class Timer{ 
    public: 
     Timer(void (*f) (void),int interval); 
     std::thread* start(); 
     void stop(); 
    private: 
     int interval; 
     bool running; 
     void (*f) (void); 
    }; 
} 
#endif 

Это таймер. cpp:

#include <thread> 
#include <chrono> 
#include "timer.h" 

timer::Timer::Timer(void (*f) (void),int interval){ 
    this->f = f; 
    this->interval = interval; 
} 

std::thread* timer::Timer::start(){ 
    this->running = true; 
    return new std::thread([this]() 
    { 
     while(this->running){ 
      this->f(); 
      std::this_thread::sleep_for(std::chrono::milliseconds(this->interval)); 
     } 
    }); 
    //return 
} 

void timer::Timer::stop(){ 
    this->running = false; 
} 

Есть ли лучшее решение для этой проблемы, или это неправильный синтаксис для передачи моей функции? Надеюсь, у кого-то есть отличное решение для этого.

+0

Посмотрите 'зЬй :: function'. –

+0

Что вам нужно - '' делегаты''. Просто найдите переполнение стека для C++ и делегатов, и вы найдете тысячи страниц;) – BitTickler

+0

@BitTickler, делегат - страшное слово, которое исходит из языка, где * указатель * запрещен, так что простой «указатель на функцию» не может быть использован. – SergeyA

ответ

2

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

Чтобы решить это, одним из решений является использование функции std :: вместо указателя функции, а затем передать необходимый код в виде лямбда.

Так указатель функция становится:

std::function<void (void)>; 

и вы могли бы назвать это так:

serverTimer = new timer::Timer([this]{onTimerTick();},1000); 
+0

Это было быстро! И это работает :) лямбда [this] {onTimerTick();} – Melvin

+0

Я лично предпочитаю 'std :: bind' в простых случаях. – SergeyA

+0

Примечание: если у вас есть класс, который имеет объект std :: function, который вставляет этот указатель в себя, рекомендуется сделать этот класс несовместимым, поскольку семантика копии неверна. – Nevin

Смежные вопросы