Массив функций
Я новичок в C++. Как сделать меню без if() {} else {}
& случай переключения()
?
Я сделал меню на массиве, но оно почему-то не компилируется. Как исправить?
typedef void (*cbd)(uint8_t, uint8_t);
typedef void (*cbt)(uint8_t, uint8_t);
typedef void (*cba)(uint8_t, uint8_t);
typedef void (*MenuFunction) (int8_t);
class Menu {
public:
Menu() {
updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes};
}
static void Setup(cbd display, cbt setTime, cba setAlarm, uint8_t alarmHours, uint8_t alarmMinutes) {
cbDisplay = display;
cbSetTime = setTime;
cbSetAlarms = setAlarm;
alarmHours = alarmHours;
alarmMinutes = alarmMinutes;
cbSetAlarms(alarmHours, alarmMinutes);
}
// Используется для обратного вызова menu.UpDown(dir)
static void UpDown(int8_t direction) {
updownFn(direction);
}
// Используется для обратного вызова menu.Tab()
static void Tab() {
updownFnNum++;
updownFn = updownFns[updownFnNum % 5];
}
private:
static void updownNone(int8_t direction) { }
static void updownAlarmHours(int8_t direction) {
alarmHours += direction;
cbDisplay(alarmHours, alarmMinutes);
cbSetAlarms(alarmHours, alarmMinutes);
}
static void updownAlarmMinutes(int8_t direction) {
alarmMinutes += direction;
cbDisplay(alarmHours, alarmMinutes);
cbSetAlarms(alarmHours, alarmMinutes);
}
static void updownTimeHours(int8_t direction) {
timeHours += direction;
cbSetTime(timeHours, timeMinutes);
cbDisplay(timeHours, timeMinutes);
}
static void updownTimeMinutes(int8_t direction) {
timeMinutes += direction;
cbSetTime(timeHours, timeMinutes);
cbDisplay(timeHours, timeMinutes);
}
static uint8_t alarmHours, alarmMinutes, timeHours, timeMinutes;
static uint8_t updownFnNum; // 0-Нет, 1-ТревогаH, 2-ТревогаM, 3-ВремяH, 4-ВремяM
static cbd cbDisplay;
static cbt cbSetTime;
static cba cbSetAlarms;
static MenuFunction updownFns[5];
static MenuFunction updownFn;
};
uint8_t Menu::alarmHours = 0;
uint8_t Menu::alarmMinutes = 0;
uint8_t Menu::timeHours = 0;
uint8_t Menu::timeMinutes = 0;
uint8_t Menu::updownFnNum = 0;
cbd Menu::cbDisplay = NULL;
cbt Menu::cbSetTime = NULL;
cba Menu::cbSetAlarms = NULL;
MenuFunction Menu::updownFn = NULL;
Вывод:
In file included from app.ino:7:0:
menu.h: In constructor 'Menu::Menu()':
menu.h:9:109: error: cannot convert '<brace-enclosed initializer list>' to 'MenuFunction {aka void (*)(signed char)}' in assignment
updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes};
Спасибо!
@Andre, 👍1
2 ответа
Лучший ответ:
В языке C++ проводится различие между инициализацией и
назначение. Инициализация — это начальное значение, которое вы даете
переменная в том месте, где вы ее определяете. Задание – это
использование оператора =
где-либо еще. Кроме того, язык не позволяет
присвоение содержимого массива в целом. Вы можете инициализировать
хотя массив.
Это:
Menu() {
updownFns[5] = {updownNone, updownAlarmHours, updownAlarmMinutes,
updownTimeHours, updownTimeMinutes};
}
является попыткой присвоить весь массив. Это не может работать. Если хотите инициализируйте массив, сделайте это в точке, где он определяется, вне определения класса:
MenuFunction Menu::updownFns[5] = {updownNone, updownAlarmHours,
updownAlarmMinutes, updownTimeHours, updownTimeMinutes};
Во-первых, ваш updownFns[5]
может содержать 5 переменных. И индекс последней переменной может быть 4, а не 5, потому что индекс массива начинается с 0.
Вот код:
typedef void (*cbd)(uint8_t, uint8_t);
typedef void (*cbt)(uint8_t, uint8_t);
typedef void (*cba)(uint8_t, uint8_t, uint8_t);
typedef void (*MenuFunction) (int8_t);
class Menu {
public:
Menu() {
updownFns[0] = updownNone;
updownFns[1] = updownAlarmHours;
updownFns[2] = updownAlarmMinutes;
updownFns[3] = updownTimeHours;
updownFns[4] = updownTimeMinutes;
}
static void Setup(cbd display, cbt setTime, cba setAlarm, uint8_t alarmHours, uint8_t alarmMinutes) {
cbDisplay = display;
cbSetTime = setTime;
cbSetAlarms = setAlarm;
alarmHours = alarmHours;
alarmMinutes = alarmMinutes;
cbSetAlarms(alarmHours, alarmMinutes);
}
// Используется для обратного вызова menu.UpDown(dir)
static void UpDown(int8_t direction) {
updownFn(direction);
}
// Используется для обратного вызова menu.Tab()
static void Tab() {
updownFnNum++;
updownFn = updownFns[updownFnNum % 5];
}
private:
static void updownNone(int8_t direction) { }
static void updownAlarmHours(int8_t direction) {
alarmHours += direction;
cbDisplay(alarmHours, alarmMinutes);
cbSetAlarms(alarmHours, alarmMinutes);
}
static void updownAlarmMinutes(int8_t direction) {
alarmMinutes += direction;
cbDisplay(alarmHours, alarmMinutes);
cbSetAlarms(alarmHours, alarmMinutes);
}
static void updownTimeHours(int8_t direction) {
timeHours += direction;
cbSetTime(timeHours, timeMinutes);
cbDisplay(timeHours, timeMinutes);
}
static void updownTimeMinutes(int8_t direction) {
timeMinutes += direction;
cbSetTime(timeHours, timeMinutes);
cbDisplay(timeHours, timeMinutes);
}
static uint8_t alarmHours, alarmMinutes, timeHours, timeMinutes;
static uint8_t updownFnNum; // 0-Нет, 1-ТревогаH, 2-ТревогаM, 3-ВремяH, 4-ВремяM
static cbd cbDisplay;
static cbt cbSetTime;
static cba cbSetAlarms;
static MenuFunction updownFns[5];
static MenuFunction updownFn;
};
uint8_t Menu::alarmHours = 0;
uint8_t Menu::alarmMinutes = 0;
uint8_t Menu::timeHours = 0;
uint8_t Menu::timeMinutes = 0;
uint8_t Menu::updownFnNum = 0;
cbd Menu::cbDisplay = NULL;
cbt Menu::cbSetTime = NULL;
cba Menu::cbSetAlarms = NULL;
MenuFunction Menu::updownFn = NULL;
// MenuFunction Menu::updownFns = {};
Но все равно код неверный. если вы посмотрите на подпись этого определения
typedef void (*cba)(uint8_t, uint8_t, uint8_t);
он принимает 3 параметра. Но внутри кода вы даете 2 параметра функции
cbSetAlarms(alarmHours, alarmMinutes)
- Работает ли конструкция int array[100] = {0} на Arduino?
- Вызов функций одного класса из другого класса — Обратный вызов
- Есть ли ограничения на размер массива в Arduino Mega 2560?
- C++ против языка Arduino?
- ошибка: ожидаемое первичное выражение перед токеном ','
- Ввести идентификатор чипа ESP32 в строковую переменную (новичок в Arduino/C++)
- Передача функции-члена класса в качестве аргумента
- Замена нескольких выводов pinMode() и digitalWrite() на массив
Это опечатка, я исправил. Но ошибка та же.
typedef void (*cba)(uint8_t, uint8_t);
, @AndreЭто не опечатка, опечатка означает что-то другое. если вы измените typedef void (*cba)(uint8_t, uint8_t, uint8_t); to typedef void (*cba)(uint8_t, uint8_t); Код скомпилируется без ошибок, @Volkan Ünal
updownFns[0] = updownNone;
Это дало: /tmp/cc3MHoSt.ltrans0.ltrans.o: в функции «глобальные конструкторы с ключом 65535_0_app.ino.cpp.o.4201»: <искусственный>:(.text.startup+0x144): неопределенная ссылка наMenu::updownFns' <искусственный>:(.text.startup+0x148): неопределенная ссылка на
Menu::updownFns' collect2: ошибка: ld вернул 1 статус выхода статус выхода 1 Ошибка компиляции для платы Arduino Pro или Pro Mini., @AndreЕсть несколько проблем с вашим кодом. Вы можете использовать вот так Уберите инициализацию из ctor и инициализируйте статическую переменную снаружи. MenuFunction Menu::updownFns[] = {updownNone, updownAlarmHours, updownAlarmMinutes, updownTimeHours, updownTimeMinutes }; Но когда вы хотите использовать updownFns, это выдаст ошибки, потому что функция также является частной в этом контексте., @Volkan Ünal
Я инициализировал массив вне определения класса. Нет ошибок. Затем я использовал
updownFns
и никаких ошибок., @AndreДа, я уже говорил об этом :), @Volkan Ünal