Указатель на метод класса внутри класса

212
22 марта 2018, 09:13

Мне понадобилась масса таймеров на чистом с++. Для решения задачи я пытаюсь использовать список, элементы которого содержат указатели на функции которые выполнятся, когда счётчик времени в элементе подойдёт к концу. Ну и раз в рабочий цикл пробегаюсь по списку и исполняю всё.
Вся эта конструкция лежит внутри родителя(CProtoLayer) класса-слоя в котором крутятся свои задачи. Как указатель я использую конструкцию void(*func)(void), но когда я пытаюсь туда вставить метод из класса-наследника(CPlLayer) компилятор ругается на несовместимость void(CPlLayer::*)(void) и void(*)(void).
Собственно как мне описать эту систему в классе родителе, чтобы потом нормально с ней работать?

Класс родитель -

class CProtoLayer
{
public:
CProtoLayer(void);
~CProtoLayer(void);
nsap my_sap;
void start_task(int param);
CMsgQueue *general_messages;
CMS_conf *configuration;
class CTimeUnit
{
public:
    CTimeUnit();
    CTimeUnit(void (*callback)(void), CProtoLayer* o);
    ~CTimeUnit();
    void SetTimer(uint32_t t);
    void Start();
    void Stop();
    uint32_t time_stump;
    uint32_t time_left;
    bool running;
    void (*callback)(void);
    CTimeUnit *next;
    CProtoLayer *owner;
};  
CTimeUnit *TimeAddUnit(void (*callback)(void));
void TimeDeleteUnit(CTimeUnit* tu);
CTimeUnit *time_head;
CTimeUnit *time_work_head;
uint32_t GetCurrentTime();
uint32_t time_old;
void TimerIrqHandler();
protected:
Nprimitive* m_rxsig;
virtual void task (void) = 0;
void send_ev(Nprimitive *prim)
{
    CMsg* tmp_msg = new CMsg();
    tmp_msg->SetPrimitive(prim);
    general_messages->PushMsg(tmp_msg);
}
}; 

класс наследник -

class CPlLayer :public CProtoLayer
{
public:
CPlLayer(void);
~CPlLayer(void);
void task(void);
PL_SAP_ns::TEXT_ind* text_msg;
DLL_SAP_ns::LC_voice_req* lcvoice_req;
DLL_SAP_ns::VOICE_data *voice_data;
CRxSimulator *simulator;
void simbegin();
};

конструктор наследника -

CPlLayer::CPlLayer(void)
{
my_sap = PL_SAP;
text_msg = new PL_SAP_ns::TEXT_ind();
text_msg->m_sap = UI_SAP;
text_msg->m_type = Nprimitive::Nindication;
text_msg->m_id = TEXT;
text_msg->str = "Hello UI from PL";
lcvoice_req = new DLL_SAP_ns::LC_voice_req();
lcvoice_req->m_sap = DLL_SAP;
lcvoice_req->m_type = Nprimitive::Nrequest;
lcvoice_req->m_id = LC_VOICE;
lcvoice_req->FID = 0;
lcvoice_req->FLCO = 0;
lcvoice_req->service = 0;
lcvoice_req->src_addr = 0;
lcvoice_req->dst_addr = 0;
lcvoice_req->BurstSetSlot(0, DT_LC_HEAD);
voice_data = new DLL_SAP_ns::VOICE_data();
voice_data->BurstSetEMB(0, 0, 0);
voice_data->m_sap = DLL_SAP;
voice_data->m_type = Nprimitive::Nrequest;
voice_data->m_id = DATA_VOICE;
voice_data->burst->data_block->data = (uint8_t*)("Hello.Good news, everyone.\n");
simulator = new CRxSimulator();
TimeAddUnit(simbegin); //ошибка здесь
}
Answer 1

Думаю, вам следует воспользоваться std::bind.

Надеюсь, вы понимаете, что void(CPlLayer::*)(void) должен получать параметр - если это нестатическая функция-член - а именно, объект, для которого она вызывается. Грубо говоря, при наличии

class Test
{
public:
    void f() { cout << "Test::f\n"; }
};

вы не можете вызвать Test::f(), и должны передать какой-то объект -

Test t;
t.f();

Ну, а чтоб все это унифицировать и позволить использовать лямбды и функциональные объекты - я бы предложил std::function. Что-то вроде

class Test
{
public:
    void f() { cout << "Test::f\n"; }
};
void g() { cout << "g\n"; }

int main(int argc, const char * argv[])
{
    Test t;
    std::function<void(void)> f[] =
        {g,std::bind(&Test::f,t), [](){cout << "lambda\n";}};
    for(auto s: f) s();
}

"По-моему, так" (с) Пух

Update

К вашему дополненному вопросу - вот тут

void (*callback)(void);

я бы использовал

std::function<void(void)> callback;

Тогда в качестве этого callback вы можете использовать все, что угодно...

READ ALSO
Как построить фрактал?

Как построить фрактал?

Принимаю любую помощь/советы в построении фракталаСама попыталась реализовать через строку и повороты (но это вроде бы фракталом не является)...

198
Как сделать контестное меню для QTableWidget в QT5.10.0

Как сделать контестное меню для QTableWidget в QT5.10.0

Здравствуйте, коллеги! Есть следующий вопросПриложение содержит, кроме всего прочего, несколько таблиц QTableWidget

221
Вопрос по поводу графа

Вопрос по поводу графа

Мне нужно в моем класе Node иметь узел на вершину что сосед с текущей вершиной и расстояние между ними то есть вес ребраКак мне это все записать?...

206
Перегрузка операций и приоритет

Перегрузка операций и приоритет

Имеется три объекта одного класса с перегруженными операциями + и *Сохранят ли эти операции приоритет или нет? Почему? Например:

191