Область видимости класса?
- Войдите на сайт для отправки комментариев
Добрый день! В проекте столкнулся с ошибками на этапе компиляции, в приведенном ниже коде сообщение об ошибке в процедуре PrintAt() "'Font' was not declared in this scope". Если класс вызывать напрямую в функции, без передачи в параметрах, то все работает, но мне как раз и нужно передать имя класса в процедуру PrintAt(). enum кидал в отдельный заголовок, не помогает. Ради интереса эту же ситуацию прогонял в Microsoft Visual Studio обыкновенным компилятором C++, все работает идеально. Начитавшись за два дня форумов, для себя сделал вывод, что возможно все дело в Arduino IDE ванильный C++ урезается, дабы несмышленый кодер не накодил чего лихого... Основной код и вызываемый класс:
enum SystemFonts { SetTimeMenu_Font, ASCII_Font }; void PrintAt(char *ch, uint8_t x, uint8_t y, SystemFonts SF); void PrintAt(char *ch, uint8_t x, uint8_t y, SystemFonts SF) { if (SF == SetTimeMenu_Font) { FONT_SetTimeMenu Font; } else if (SF == ASCII_Font) { FONT_ASCII Font; } Serial.println(Font.FONT_WIDTH); } void TimeSettings(){ PrintAt("00:00", 0, 0, SetTimeMenu_Font); }
class FONT_SetTimeMenu { public: const int FONT_ARRAY[11][20] = { {0x00, 0x00, 0xFC... {0x00, 0x00, 0x00... {0x00, 0x00, 0x0C... . . . }; const int FONT_WIDTH = 20; const int FONT_HEIGHT = 11; const int FONT_START_CHAR = 0x30; const int FONT_CHAR_WIDTH = 10; const int FONT_CHAR_HEIGHT = 16; };
Заранее благодарен за помощь!!!
В твоем коде Font не определен. У тебя две совершенно разные переменные в разных контекстах. Так работать не будет. И объявлять огромную переменную на стеке функции глубоко в дереве вызовов - дурацкая затея.
область действия такая же, как у обычных переменных - до выхода из блока.
Поэтому область действия переменной Font, обьявленной в строке 10, заканчивается у скобки в строке 11. Закономерно что в строке 15 вы получаете ошибку.
В твоем коде Font не определен. У тебя две совершенно разные переменные в разных контекстах. Так работать не будет. И объявлять огромную переменную на стеке функции глубоко в дереве вызовов - дурацкая затея.
Как же правильно сделать в этом случае? У меня несколько классов со шрифтами и одна процедура для их вызова.
Как же правильно сделать в этом случае?
вариантов дофига
Например переместить строчку 15 внутрь блоков. где обьявлен Font или использовать перегрузку функций... или шаблоны под каждый тип фонта...
В любом случае, если классы фонтов существенно разные и не связаны наследованием. написать одну функцию, работающую с разными фонтами - не получится.
область действия такая же, как у обычных переменных - до выхода из блока.
Поэтому область действия переменной Font, обьявленной в строке 10, заканчивается у скобки в строке 11. Закономерно что в строке 15 вы получаете ошибку.
Да, перепроверил, я и в MVS неправильно смоделировал ситуацию, и пошел не в том направлении.
Как же правильно сделать в этом случае? У меня несколько классов со шрифтами и одна процедура для их вызова.
Ну для начала наверно понять зачем нужны классы и почему в твоем случае ты создаешь себе только лишний геморрой.
Потом определить нормальные глобальные константы в progmem, и обернуть работу с ними в класс с легким экземпляром содержащим только адрес константы, если уж так хочется.
вариантов дофига
Например переместить строчку 15 внутрь блоков. где обьявлен Font или использовать перегрузку функций... или шаблоны под каждый тип фонта...
В любом случае, если классы фонтов существенно разные и не связаны наследованием. написать одну функцию, работающую с разными фонтами - не получится.
Пытался посмотреть как это реализовано в адафрут, шрифты в заголовочных файлах в виде двух массивов, две структуры с описанием, а вот дальше не понял, указатели на указателях и указателями погоняют)
По вопросу, универсальный алгоритм уже написал, работает, вместо него в примере заглушка Serial.print... для наглядности и простоты примера.
Ну для начала наверно понять зачем нужны классы и почему в твоем случае ты создаешь себе только лишний геморрой.
Потом определить нормальные глобальные константы в progmem, и обернуть работу с ними в класс с легким экземпляром содержащим только адрес константы, если уж так хочется.
Похоже так и поступлю, без классов, для тех трех шрифтов вызову свои процедуры, они небольшие. Тем более progmem не работает с классами в ардуино, ну или работает, но с костылями...
Тем более progmem не работает с классами в ардуино, ну или работает, но с костылями...
фигня.
работает ровно так же, как и без классов...
Классы - не более чем абстракция для удобства программиста.
фигня.
работает ровно так же, как и без классов...
Классы - не более чем абстракция для удобства программиста.
Откройте секрет, на форумах пишут, что классы и конструкты не поддерживаются прогмемом. Ну по крайней мере у меня, словно в подтверждение этой информации компилятор отказался записывать во флеш.
Да, кстати, а если сделать константный класс, поля которого не изменяюся во время выполнения, можно ли его в PROGMEM запхать, как обычную строку? Если у него виртуальных методов не будет, то компилятор и VMT создавать не будет, наерна. Или класс на 146% состоящий из одних static constexpr.
Всё, вопрос дебильный, конструктор всё равно должен вызваться, чтоб инициализировать поля.
Откройте секрет, на форумах пишут, что классы и конструкты не поддерживаются прогмемом.
а как же фонты от адафруит? Фонты это именно структуры и их экземпляры отлично кладутся в прогмем.
Что касается классов - то поясните, что вы подразумеваете под идеей "положить класс в прогмем". Класс - это описание данных и методов работы с ними. Положить класс в прогмем нельзя точно так же, как нельзя сохранить в прогмеме цикл или функцию. А вот данные экземпляра класса положить в прогмем можно. если вы, конечно, дружите с такими понятиями как бинарное представление данных и указатели...
Да, кстати, а если сделать константный класс, поля которого не изменяюся во время выполнения, можно ли его в PROGMEM запхать, как обычную строку?
вопрос тот же, что и ТС - ты что в прогмем класть собрался - класс или экземпляр?
а как же фонты от адафруит? Фонты это именно структуры и их экземпляры отлично кладутся в прогмем.
Что касается классов - то поясните, что вы подразумеваете под идеей "положить класс в прогмем". Класс - это описание данных и методов работы с ними. Положить класс в прогмем нельзя точно так же, как нельзя сохранить в прогмеме цикл или функцию. А вот данные экземпляра класса положить в прогмем можно. если вы, конечно, дружите с такими понятиями как бинарное представление данных и указатели...
Так ведь у адафрут шрифт это заголовочный файл в котором хранится обыкновенный массив, вот пример, у меня как раз открыт был:
Вторая таблица это описание шрифтов, т.к. насколько понял, они для экономии памяти еще и рисуют их нетривиально.
а как же фонты от адафруит? Фонты это именно структуры и их экземпляры отлично кладутся в прогмем.
Что касается классов - то поясните, что вы подразумеваете под идеей "положить класс в прогмем". Класс - это описание данных и методов работы с ними. Положить класс в прогмем нельзя точно так же, как нельзя сохранить в прогмеме цикл или функцию. А вот данные экземпляра класса положить в прогмем можно. если вы, конечно, дружите с такими понятиями как бинарное представление данных и указатели...
Да, мне как раз данные экземпляра класса и нужно хранить, это константы.
а как же фонты от адафруит? Фонты это именно структуры и их экземпляры отлично кладутся в прогмем.
Что касается классов - то поясните, что вы подразумеваете под идеей "положить класс в прогмем". Класс - это описание данных и методов работы с ними. Положить класс в прогмем нельзя точно так же, как нельзя сохранить в прогмеме цикл или функцию. А вот данные экземпляра класса положить в прогмем можно. если вы, конечно, дружите с такими понятиями как бинарное представление данных и указатели...
Так. Я не доглядел ниже, в заголовочном файле с массивами шрифтов у Адафрут есть в самом низу инициализация структуры
И в заголовочном файле со структурами само определение структуры
Теперь немного яснее становится)
Вторая таблица это описание шрифтов
это структура, которую, как вы пишете, нельзя сохранить в прогмеме...:)
описание этой структуры находится в файле glcfont.h
И в заголовочном файле со структурами само определение структуры
Теперь немного яснее становится)
как вы можете видеть, описание структуры во флеш не пишется(нет спецификатора PROGMEM). А вот данные конкретного экземпляра (фонта) - в прогмеме (спецификатор есть)
как вы можете видеть, описание структуры во флеш не пишется(нет спецификатора PROGMEM). А вот данные конкретного экземпляра (фонта) - в прогмеме (спецификатор есть)
О да, нужно быть внимательней, спасибо!:)
как вы можете видеть, описание структуры во флеш не пишется(нет спецификатора PROGMEM). А вот данные конкретного экземпляра (фонта) - в прогмеме (спецификатор есть)
Кстати, я использую буфер памяти для дисплея в виде двумерного массива, хотя, как погляжу, многие используют одномерный. Соответственно я и массив шрифтов использую тоже двумерный, просто потому что мне так проще показалось, работать с двумя координатами, а не пересчитывать из одномерного в две координаты при выводе на дисплей. Есть ли на ваш взгляд принципиальная причина применения именно одномерного буфера?
Есть ли на ваш взгляд принципиальная причина применения именно одномерного буфера?
многомерные массивы в си - это всего лишь внешнее представление для программиста. Массивы a[2][2] и b[4] в памяти представлены одинаково. Поэтому что в данном случае удобнее. то и используйте
Понял, спасибо!