Перечисление классов не было объявлено в этой области
Я программирую Arduino. В том же файле .ino, что и setup()
и loop ()
, я определил следующее:
void setup()
{
// код настройки
}
enum class CYCLE { TypeA, TypeB };
String cycleToString (CYCLE cycle) {
if (cycle == CYCLE::TypeA) {
return "TypeA";
}
else if (cycle == CYCLE::TypeB) {
return "TypeB";
}
return "Undefined";
}
void loop()
{
// код цикла
}
Но при компиляции он выдает ошибку:
sketch_v1:37:22: error: 'CYCLE' was not declared in this scope
String cycleToString (CYCLE cycle) {
^
/Users/.../sketch_v1.ino: In function 'String cycleToString(CYCLE)':
sketch_v1:37:31: error: 'String cycleToString(CYCLE)' redeclared as different kind of symbol
String cycleToString (CYCLE cycle) {
^
/Users/.../sketch_v1.ino:37:8: note: previous declaration 'String cycleToString'
String cycleToString (CYCLE cycle) {
^
Обратите внимание, что класс enum
отлично работает и работает так, как задумано, но если я попытаюсь добавить функцию, полагаясь на тип ЦИКЛА, это приведет к ошибкам.
@AJP, 👍4
Обсуждение4 ответа
Лучший ответ:
Это известная ошибка Arduino builder, если у вас есть функции перед структурами, классами или перечислениями в sketch.
Скетч:
void foo() {
}
enum class CYCLE { TypeA, TypeB };
String cycleToString (CYCLE cycle) {
if (cycle == CYCLE::TypeA) {
return "TypeA";
}
else if (cycle == CYCLE::TypeB) {
return "TypeB";
}
return "Undefined";
}
void setup() {
}
void loop() {
}
обрабатывается в этот файл .cpp
#include <Arduino.h>
#line 1 "/tmp/arduino_modified_sketch_327776/sketch_jun23a.ino"
#line 1 "/tmp/arduino_modified_sketch_327776/sketch_jun23a.ino"
#line 2 "/tmp/arduino_modified_sketch_327776/sketch_jun23a.ino"
void foo();
#line 7 "/tmp/arduino_modified_sketch_327776/sketch_jun23a.ino"
String cycleToString(CYCLE cycle);
#line 17 "/tmp/arduino_modified_sketch_327776/sketch_jun23a.ino"
void setup();
#line 22 "/tmp/arduino_modified_sketch_327776/sketch_jun23a.ino"
void loop();
#line 2 "/tmp/arduino_modified_sketch_327776/sketch_jun23a.ino"
void foo() {
}
enum class CYCLE { TypeA, TypeB };
String cycleToString (CYCLE cycle) {
if (cycle == CYCLE::TypeA) {
return "TypeA";
}
else if (cycle == CYCLE::TypeB) {
return "TypeB";
}
return "Undefined";
}
void setup() {
}
void loop() {
}
как вы можете видеть, прямые объявления функций находятся перед первой функцией, поэтому перед перечислением.
Обходной путь для этой ошибки состоит в том, чтобы следовать хорошей практике и объявить все структуры, перечисления и классы перед первым определением функции.
пожалуйста, посмотрите мой ответ. Если вы можете отредактировать свой, чтобы включить / уточнить это, я удалю свой и отмечу ваш как правильный. Большое спасибо., @AJP
@AJP, я знаю об этой ошибке, поэтому я определил ее в вашем вопросе, но я не мог знать, какая функция у вас есть до перечисления. Я написал ответ более общий. Теперь я добавил кое-что о обходном пути., @Juraj
Выполнено. Спасибо @Juraj, @AJP
+1 за ответ и -1 за Arduino IDE. Действительный C++ должен просто компилироваться. Я не хочу изучать особенности другого языка программирования, если я уже умею программировать на C++. Я не могу поверить, что это не было решено за последние 4 года., @Thomas Weller
Я не понимаю обходной путь. У меня уже есть перечисление, объявленное перед функцией, использующей его в качестве аргумента, но я все равно получаю ошибку., @AgainPsychoX
@AgainPsychoX, ты должен ставить его перед всеми функциями, @Juraj
Обратите внимание, что это не ответ, так как ваш код идеально компилируется. (добавление функции настройки/цикла по умолчанию/пустой настройки / цикла).
Тем не менее, я хочу привести некоторые улучшения, которые не могут вписаться в комментарий:
- (необязательно) Выровняйте { и } друг под другом. Некоторые ставят { за черту, некоторые на новую черту; в основном это предпочтение. Но выравнивание { и } в основном более четкое.
- Поместите каждое значение типа/перечисления в новую строку; это облегчает добавление комментариев выше/после нее.
- За исключением тривиальных случаев, никогда не возвращайтесь из заявления, кроме последнего. В вашем случае функция довольно проста, но все же лучше сохранять возврат только в конце функции.
- Используйте
инструкцию switch вместо нескольких
инструкций if.
Таким образом, вы получаете:
enum class CYCLE
{
TypeA,
TypeB
};
String cycleToString (CYCLE cycle)
{
String str;
switch (cycle)
{
case CYCLE::TypeA:
str = "TypeA";
break;
case CYCLE::TypeB:
str = "TypeB";
break;
default:
str = "Undefined";
break;
}
return str;
}
Спасибо, Мишель. Полностью согласен с несколькими строками в перечислении. Я сократил его, чтобы помочь сократить вопрос. Мне нравится идея расположить " {"и"} " по вертикали. Сейчас я внес это изменение, и это хорошо, спасибо. Я не согласен с утверждением о переключении, так как мне не нравится ошибка с ошибкой, если вы забудете перерыв. Предупреждают ли вас распространенные C++ IDE? В качестве преимущества "переключения": предупреждает ли C++ об ошибке/, если вы не обрабатываете все типы перечислений? Возвращайтесь только один раз: да, полностью согласен. Спасибо., @AJP
Пожалуйста. Оператор if может быть столь же опасным (использование = вместо ==). Я не думаю, что вы получите предупреждение, забыв о перерыве (вы можете легко попробовать). C++ не предупреждает вас о том, что вы не проверяете все значения перечисления, но именно для этого используется ключевое слово "по умолчанию"., @Michel Keijzers
Верно. Я понимаю. По вашему опыту, является ли "если (a = x)` более распространенной ошибкой, чем забывание "перерыва"? Я предполагаю, что в конечном итоге все сводится к практике (?), Но я делал первое, возможно, 2 раза в своей жизни, но позже намного чаще, поэтому я лично избегаю "переключения" по этой причине., @AJP
Возможно, вам захочется прочитать: https://stackoverflow.com/questions/97987/advantage-of-switch-over-if-else-statement (на самом деле мне тоже было любопытно). В любом случае, переключатель более удобочитаем. Во всех (профессиональных) программных проектах, которые я выполнял, проверка кода не передавала бы кучу операторов if над переключателем (при сравнении с одной переменной). Кстати, я проверил, Arduino IDE не показывает никаких предупреждений (даже со всеми включенными предупреждениями)., @Michel Keijzers
Даже Visual Studio 2019 с включенными предупреждениями не отображается. Я работал с lint (статическая проверка C/C++), и я совершенно уверен, что в приложении упоминается забытый перерыв. Хотя в C разрешено иметь несколько операторов case (для выполнения одного и того же действия для нескольких значений). В основном люди ставят // Проваливаются за это, чтобы показать, что разрыв намеренно забыт., @Michel Keijzers
Это работает, если вы переместите класс перечисления
наверх, т. е.:
enum class CYCLE { TypeA, TypeB };
void setup()
{
// setup code
}
String cycleToString (CYCLE cycle) {
if (cycle == CYCLE::TypeA) {
return "TypeA";
}
else if (cycle == CYCLE::TypeB) {
return "TypeB";
}
return "Undefined";
}
void loop()
{
// loop code
}
Я нашел обходной путь на форумах Arduino: Разместите перечисления отдельно файл (я использую enums.hpp
) и включаю его из основного файла скетча (.ino
), например #include "enums.hpp" ;
.
включен ли у вас файл .hpp в то же место в ino, где изначально было перечисление?, @Juraj
- Какие накладные расходы и другие соображения существуют при использовании структуры по сравнению с классом?
- Что лучше использовать: #define или const int для констант?
- Функции со строковыми параметрами
- Как работать с аналоговыми контактами в цикле?
- Какие есть другие IDE для Arduino?
- Как использовать переменные и функции в нескольких файлах .ino
- Разница между void setup() и void setup(void)
- Будет ли .ino-скетч ардуино компилироваться непосредственно на GCC-AVR?
Arduino builder имеет проблемы, если структуры, перечисления, классы не определены до первой функции, @Juraj
почему вы пишете "enum class` вместо просто "enum"?, @chrisl
@chrisl,
enum class
илиenum struct
из C++11-это перечисление, где значения могут использоваться только с именем типа перечисления типаCYCLE::TypeB
., @JurajНе могли бы вы привести пример, который воспроизводит эту ошибку comiler? Я встроил ваш код в шаблон ' setup()
-
loop ()`, и он работает!, @Sim SonСделано @SimSon, и именно там скрывался "жучок". См.Ответ Юрая., @AJP