#c #arduino #overloading #overload-resolution
#c #arduino #перегрузка #перегрузка-разрешение
Вопрос:
Я совсем новичок в C , и, вероятно, у меня были наивные проблемы. Я знаю, что есть и другие вопросы, связанные с смайликами, но они связаны (как мне кажется) с более сложными проблемами, чем мои. Я пытаюсь создать прошивку для Arduino, используя C , и я поранился из-за ошибок перегрузки.
У меня есть этот код, определенный в файле cpp:
void class1::functionA(void)
{
object2.functionOfClass2(class1::functionB);
}
Class1 инициализируется как:
class class1
{
public:
void functionA(void);
void functionB(void);
private:
}
И в компиляции дает
no matching function for call to 'class2::functionOfClass2(<unresolved overloaded function type>)'
Перевод на практический:
в моем коде я использую библиотеку Wire внутри функции-члена class1 для библиотеки Arduino, где в примере object2 и class2 являются соответственно объектом Wire класса TwoWire.
Мне нужно вызвать библиотеку wire внутри функции-члена моего class1. Это решение является следствием предыдущих уроков, в которых я узнал, что я не могу вызвать функцию-член class1 внутри функции, не являющейся членом, потому что создание экземпляра функции, не являющейся членом, невозможно, поскольку экземпляр класса еще не создан как объект, и компилятор не имеет понятия окак это сделать.
Но вызов провода.объект внутри функции-члена, я думал, что это возможно. Но лучше подумать об этом, на самом деле, при передаче указателя функции-члена class1 функции Wire компилятор не может знать, что передавать в wire, и поэтому следующее НЕВЕРНО:
void class1::functionA(void)
{
Wire.onRequest(class1::functionB); //wrong
}
где onRequest принимает void (*)(void)
функции.
Итак, попытка с
void class1::functionA(void)
{
Wire.onRequest(amp;class1::functionB); //wrong
}
Ошибка стала:
ошибка: нет соответствующей функции для вызова ‘TwoWire:: onRequest (void (class1::*) ())’ кандидатами являются: void TwoWire :: onRequest (void (*) ())
Есть способ заставить эти вещи работать? Если я скажу static и список инициализаторов, я на правильном пути с правильными ключевыми словами?
Комментарии:
1. Пришлось удалить мой ответ. Я не думаю, что это просто выполнимо. Вам нужно передать
this
свойclass1
экземплярonRequest
, и вы просто не можете этого сделать, если он принимаетvoid (*)()
(параметры не разрешены). Хорошо спроектированная библиотека вместо этого определилаonRequest
бы asonRequest(void (*callback)(void*), void* context)
вместо, и вы бы передалиthis
ascontext
.2. Единственный способ сделать это — если
class1
во всем вашем приложении есть только один экземпляр — тогда вы можете безоговорочно заменить этот экземпляр и вызватьfunctionB
его.
Ответ №1:
amp;class1::functionB
это указатель на функцию-член, а не указатель на функцию. Его тип void (class1::*)(void)
не void (*)(void)
соответствует ожидаемому onRequest
методом. Это означает, что для вызова этой функции-указателя на член необходимо также иметь экземпляр ( class1*
) .
Если class1
это одноэлементный элемент, самый простой способ решить эту проблему, вероятно, создать functionB
статический член или просто функцию, не являющуюся членом (не внутри какого-либо класса).
Если class1
невозможно предположить, что одноэлементный, то в библиотеке должен быть способ передать указатель контекста (обычно void*
) вдоль указателя на функцию, и этот контекст является параметром функции обратного вызова. Вы должны передать this
в качестве контекста и указателя на функцию-оболочку, например, следующим образом:
void wrapper_for_class1_functionB(void* context)
{
static_cast<class1*>(context)->functionB();
}
void class1::functionA(void)
{
Wire.onRequest(amp;wrapper_for_class1_functionB, this);
}
Комментарии:
1. Цель состоит не в том, чтобы сделать его одноэлементным, фактически также структуры данных определены в классе. Это означает, что я не могу использовать функцию, не являющуюся членом, поскольку она содержит обработку данных структур, определенных в классе.
2. Затем я попробовал ваше предложение, кажется очень интересным, но для этого опять же требуется изменить библиотеку Wire, чтобы принять другой аргумент. Фактически, ошибка, которую я получил, — это несоответствующая функция. Я что-то упускаю?
3. И в любом случае, кроме функций в «functionB ()» есть и другие функции-члены, которые необходимо вызывать вне .cpp, поэтому в основном файле при создании объекта.
4. Если библиотека не предоставляет аргумент контекста, который передается обратно с обратным вызовом, то для пользовательского кода, который установил обратный вызов, невозможно узнать, в каком контексте выполняется обратный вызов, просто потому, что обратный вызов не получает контекст. И
Wire::onRequest
действительно не предоставляет его. Лучшее, что вы можете сделать, это сохранить контекст (this
в вашем случае указатель) в глобальной переменной и убедиться, что никакие два экземпляра не могут ждать обратного вызова одновременно.