#c #function-pointers
#c #указатели на функции
Вопрос:
После удаления всех определений типов у меня есть следующие объявления:
class Message {
protected:
Message* (*factories[N])(HardwareSerial);
...
}
class DebugMessage : Message {
protected:
Message* receive(HardwareSerial serial);
...
public:
DebugMessage(char* message);
...
};
Message* DebugMessage::receive(HardwareSerial serial){...}
DebugMessage::DebugMessage(char* message){
...
factories[DEBUG_MESSAGE] = amp;DebugMessage::receive;
...
}
Однако, когда я пытаюсь его скомпилировать, я получаю сообщение об ошибке при назначении с указанием
debugMessage.cpp: In constructor ‘DebugMessage::DebugMessage(char*)’:
debugMessage.cpp:4:28: error: cannot convert ‘Message* (DebugMessage::*)(HardwareSerial)’ to ‘Message* (*)(HardwareSerial)’ in assignment
factories[DEBUG_MESSAGE] = amp;DebugMessage::receive;
Ответ №1:
Вам нужно уточнить точный тип указателя на функцию, который вам нужно сохранить в вашем массиве:
class Message {
protected:
Message* (DebugMessage::*factories[N])(HardwareSerial);
...
}
ОБНОВЛЕНИЕ (немного подробнее)
Причина такого уточнения типа данных заключается в том, что функции-члены имеют дополнительный (скрытый) первый параметр this
, о котором компилятор должен знать при вызове его через указатель на функцию.
Сказав это, я должен указать, что static
функции-члены не имеют такого ограничения (поскольку у них нет this
параметра) и могут быть «свободно смешаны» со свободными функциями в этом отношении
Комментарии:
1. Исправление: указатели на свободные функции и указатели на функции-члены — это разные типы.
Ответ №2:
@YePhlcK объяснил, почему у вас возникла проблема, но я не знаю, действительно ли опубликованный им код решает проблему. Я думаю, что вы сможете добавлять указатели на DebugMessage
функции-члены только как фабрики, используя это. Я изменил ваш код, чтобы он компилировался и использовался std::function
, и std::bind
чтобы получить указатель функции на функцию-член.
#include <functional>
class HardwareSerial {};
class Message {
public:
using Reciever = Message*(HardwareSerial);
protected:
std::function<Reciever> factories[10];
};
class DebugMessage : Message {
protected:
Message* receive(HardwareSerial serial);
public:
DebugMessage(char* message);
};
Message* DebugMessage::receive(HardwareSerial serial){ return nullptr; }
DebugMessage::DebugMessage(char* message){
factories[0] = std::bind(amp;DebugMessage::receive, this, std::placeholders::_1);
}
Таким образом, в вашем массиве могут быть функции-члены и функции, не являющиеся членами, а также лямбды и функциональные объекты. Вам нужно использовать только std::bind
с функциями-членами.
Комментарии:
1. Оба эти ответа были действительно хорошими. Если бы кто-нибудь нашел этот вопрос, я бы порекомендовал им кодировать таким образом. При этом я выбрал другой ответ, потому что он прямо ответил на мой вопрос (даже если это менее правильный способ кодирования).