Создание пользовательского класса
- Войдите на сайт для отправки комментариев
Пт, 03/03/2017 - 21:07
Добрый всем вечер.
Проблема банальна: нужно вынести пользовательские функции в отдельные файлы или файл. Чем больше читаю о создании классов или библиотек, тем больше убеждаюсь что это либо слишком сложно для меня либо вообще неприемлемо.
Вся беда в том, что мне нужно производить некоторые действия с помощью элементов библиотеки UTFT. Создаю свой класс, но он не проходит компиляцию, потому что в нем используются элементы другого класса.
Так что, получается что эта затея обречена? Вот коды моих изысков:
1. Сам скетч:
#include <UTFT.h> UTFT myGLCD(ILI9327, 38, 39, 40, 41); extern uint8_t BigFont[]; extern uint8_t SmallFont[]; extern uint8_t Dingbats1_XL[]; extern uint8_t battery_24x48[]; //******************** SETUP **************** void setup () { myGLCD.InitLCD(); // запуск дисплея myGLCD.clrScr(); // очистка дисплея myGLCD.setFont(SmallFont); } void loop() {};
2. Заголовок "user.h":
#ifndef user_h #define user_h #endif class user { public: void InitEMU(); };
3. Класс "user.cpp":
#include "user.h" void user::InitEMU() { myGLCD.setFont(SmallFont); myGLCD.setColor(VGA_WHITE); myGLCD.print("Init start:", 0, 220); delay(210); myGLCD.print(" ", 0, 220); myGLCD.setColor(VGA_WHITE); myGLCD.print("Init start:", 0, 210); myGLCD.print("Loading", 0, 220); delay(310); for (int i = 0; i <= 75; i = i + 9) { myGLCD.print(".", 75 + i, 220); delay(40); } myGLCD.print(" ", 0, 220); myGLCD.print("Init start:", 0, 200); myGLCD.print("Loading .......... Done!", 0, 210); delay(340); myGLCD.print("Init start:", 0, 190); myGLCD.print(" ", 0, 210); myGLCD.print("Loading .......... Done!", 0, 200); myGLCD.print("Init sensors: ", 0, 220); myGLCD.setFont(battery_24x48); delay(340); myGLCD.print(String(9), 110, 215); delay(340); myGLCD.print(String(8), 110, 215); delay(340); for (int i = 1; i <= 6; i++) { myGLCD.print(String(i), 110, 215); delay(200); } myGLCD.print("7", 110, 215); delay(300); myGLCD.print("6", 110, 215); delay(300); myGLCD.print("7", 110, 215); delay(300); myGLCD.print("6", 110, 215); delay(300); myGLCD.print("7", 110, 215); }
Я хочу знать только одно: можно ли внутри своего класса использовать элементы другого?
Можно. Но не всегда так, как вы желаете.
Пока вас, по старой русской традиции, не начали учить ухватом - сбегайте в гугл и почитайте про наследование классов, например. Или, хотя бы, сделайте myGLCD членом своего класса.
P.S. #endif ставят в конце защищаемого .h, иначе смысла в этой конструкции никакого нет.
Buzzer2010, а почему класс, который Вы хотите использовать из своего класса, описан снаружи класса?
Buzzer2010, а почему класс, который Вы хотите использовать из своего класса, описан снаружи класса?
Потому что я еще не умею правильно описывать классы. Это прежде всего. Покажите 1 раз как правильно пожалуста.
Можно. Но не всегда так, как вы желаете.
Пока вас, по старой русской традиции, не начали учить ухватом - сбегайте в гугл и почитайте про наследование классов, например. Или, хотя бы, сделайте myGLCD членом своего класса.
P.S. #endif ставят в конце защищаемого .h, иначе смысла в этой конструкции никакого нет.
Спасибо. Признаться я просто скопировал структуру класса из какого-то примера, не вникая в смысл происходящего.
Значит тогда вот так?:
1
Ну, переменная myGLCD в файле user.cpp используется? А описывать её за Вас Трамп будет? Опишите её и всего делов.
Вставьте в начало файла что-нибудь типа
Только вот знаете чего я никак не пойму? Вот нахрена Вам класс? Почему не использовать просто вункцию во внешнем файле? Какой кайф Вы планируете извлечь и того, что у Вас там именно класс?
Ну, переменная myGLCD в файле user.cpp используется? А описывать её за Вас Трамп будет? Опишите её и всего делов.
Вставьте в начало файла что-нибудь тпа
Только вот знаете чего я никак не пойму? Вот нахрена Вам класс? Почему не использовать просто вункцию во внешнем файле? Какой кайф Вы планируете извлечь и того, что у Вас там именно класс?
Вот спасибо что и Вы тоже откликнулись. Нахрена мне класс? Читал про библиотеки и классы и было высказано мнение что использование классов более желательно чем библиотеки. С точки зрения оптимизации. Кроме того, я хочу собрать все свои уже отлаженные и далее не редактируемые функции в один файл. А насколько я понял так сделано в "UTFT.cpp", которую я тут изучаю...
Сделал так как Вы подсказали:
user.cpp:2: error: 'UTFT' does not name a type
extern UTFT myGLCD;
было высказано мнение что использование классов более желательно чем библиотеки. С точки зрения оптимизации.
Видимо, там был другой случай и это было действительно так. В вашем же случае использование класса проигрывает и по памяти и по времени.
Отдельные функции делаются также. Есть заголовочный файл и файл кода. например, мне нужны две функции void kaka(const int) и long mumu(void). окей, делаю файл mylib.h примерно такой
и файл кода mylib.cpp
И все дела.
Кстати, необходимость описывать все используемые переменные (о чм я выше писал) это не отменяет. Трам - зараза за Вас не опишет :)
Сделал так как Вы подсказали:
user.cpp:2: error: 'UTFT' does not name a type
extern UTFT myGLCD;
Про #include не забыли точно? Он точно такой же как и в основном скетче? И всё с этим файлом в порядке? Так не бывает, ищите какую-то фигню.
было высказано мнение что использование классов более желательно чем библиотеки. С точки зрения оптимизации.
Видимо, там был другой случай и это было действительно так. В вашем же случае использование класса проигрывает и по памяти и по времени.
Отдельные функции делаются также. Есть заголовочный файл и файл кода. например, мне нужны две функции void kaka(const int) и long mumu(void). окей, делаю файл mylib.h примерно такой
и файл кода mylib.cpp
И все дела.
Кстати, необходимость описывать все используемые переменные (о чм я выше писал) это не отменяет. Трам - зараза за Вас не опишет :)
Трамп - он такой, да. Действует по принципу: "Обещать - не значит жениться"
А скажите - можно все свои функции собрать в одном файле или для каждой надо писать отдельно хедэр и .cpp?
Описывать перменные мне не трудно. Да только - как? extern не прокатило, к сожалению (((((
Вот как дело было:
Теперь орёт на " myGLCD.setFont(SmallFont);" :
user.cpp:7: error: 'SmallFont' was not declared in this scope
Шрифты тоже тут объявлять нужно?
-----------------------
Вот так - совсем не орал:
А теперь же можно тут и другие функции свои поописывать и хэдер подправить?
Кстати: в какие скобки брать этот user.h в #include в самом скетче: в кавычки или в такие: <> ??? и какая в них разница ?
Смотрите на каждый файл с точки зрения компилятора: возможно ли использовать неизвестный объект? Вот вы, к примеру, можете процитировать стихотворение малоизвестного автора, если я вам сообщу его название? Вот и компилятор тоже...
Только копировать не нужно во все файлы одно и то же. #include придумали, чтобы такой ерундой не страдать.
Это еще нужно разобраться... Пока что: "многабукаф" ))))))) Но - спасибо. Любой совет мотаю на ус...
Ой. А как теперь из скетча вызвать эту функцию или элемент класса? Пишет вот что:
Вызываю вот так:
user.cpp:7: error: 'SmallFont' was not declared in this scope
Так правильно. Описывать нужно все переменные. myGLCD Вы описали, а шрифты чем хуже?
Другое дело, если вы эти описания шрифтов (всех) поемстите в user.h, то Вам их не нужно будет описывать ни в основном скетче, ни в user.cpp - они будут в одном месте и это правильно.
А теперь же можно тут и другие функции свои поописывать и хэдер подправить?
Ну я же приводил Вам пример для двух функций. В хеадере описываете все прототипы (хоть сто функций), а исполняеммо файле пишете сами функции.
Кстати: в какие скобки брать этот user.h в #include в самом скетче: в кавычки или в такие: <> ??? и какая в них разница ?
Это к сожалению ещё один "тот самый" момент в который разработчики IDE полазали грязными руками и сделали правки за Вас.
Общее правило таково: <> используется в том случае, когда .h файл находится в всистемных папках для включаемых файлов, а "" - в том случае, когда файл в той же папке, что и скетч. Но, повторяю, разработчики IDE тут немного пошустрили. Более того, это зависит от версии IDE. Как они сделали описано в какой-то их документации, я видел, но не помню где. Как таковой проблемы у меня не возникало, потому плотно и не разбирался.
Ой. А как теперь из скетча вызвать эту функцию или элемент класса? Пишет вот что:
Вам бы всё-таки книжку почитать. Потому, что ответ на большинство Ваших вопросов (и на этот) примерно такой "есть 100500 способов, а как Вам надо?"
Ну, вот смотрите. Вы описали класс (тип данных) с именем user. Запомните, класс это тип данных. Теперь, чтобы им пользоваться, необхожимо описать хотя бы одну переменную этого типа (называется "экземпляр класса"). Например:
а потом уже вызывать метод "в контексте экземпляра"
Но при том классе, что у Вас, как таковой экземпляр Вам не нужен, т.к. у него свойств нет, поэтому метод InitEMU можно сделать статическим (добавить слово static в его описание в .h файле) и тогда его можно вызывать по имени класса без экземпляра, но не через точку, а через :: Пример так
Так. Спасибо за разъяснения. Сейчас буду постигать.
Со скобками: я думал, примерно, тоже самое, но хотел услышать мнение специалиста.
УРРА! Заработало!!!! Вот спасибо Вам большое !!!! Будет чем на работе заняться: перенесу все свои отлаженные процедурки в один .cpp !!!!
а потом уже вызывать метод "в контексте экземпляра"
Но при том классе, что у Вас, как таковой экземпляр Вам не нужен, т.к. у него свойств нет, поэтому метод InitEMU можно сделать статическим (добавить слово static в его описание в .h файле) и тогда его можно вызывать по имени класса без экземпляра, но не через точку, а через :: Пример так
Да, я уже заметил что-то неладное с UTFT и с созданием элемента класса "myGLCD" в строке:
Там явно создаётся еще одна переменная и только она потом вызывается через точку со всеми другими элементами UTFT. Я так делал - ничего не вышло почему-то ((( А почему?
Там явно создаётся еще одна переменная и только она потом вызывается через точку со всеми другими элементами UTFT. Я так делал - ничего не вышло почему-то ((( А почему?
Ответить на этот вопрос можно только при одновременном выполнении сразу двух условий:
1. В сообщении с вопросом присутствует полный скетч.
2. В сообщении с вопросом присутствует подробное описание, чего именно Вы хотите добиться, и чем то, что получается, отличается от желаемого.
Мне кажется, что ЕвгенийП прав - классы вам пока не нужны. Просто научитесь для начала разбивать код на разные файлы. Потом поработайте со структурами (struct), поймете что есть форма и что есть содержание, как крутить полями и почему там что-то "вызывается через точку". А затем уже до классов там рукой подать.
Поверьте - редко кому удается с нуля взять и лупануть собственный класс, учтя все подводные камни. А вы еще и на достаточно сложном примере начали экспериментировать.
P.S. Для простых вещей (экспериментов) не стоит мучать сразу Arduino IDE с ее специфическими операторами. Я, к примеру, не завязанные на железе вещи, вообще в CodeLite сначала делаю. Там и дебаг есть и всё такое. А компилятор точно такой же, как в Arduino IDE. Так что при переносе возникает минимум проблем.
а потом уже вызывать метод "в контексте экземпляра"
Но при том классе, что у Вас, как таковой экземпляр Вам не нужен, т.к. у него свойств нет, поэтому метод InitEMU можно сделать статическим (добавить слово static в его описание в .h файле) и тогда его можно вызывать по имени класса без экземпляра, но не через точку, а через :: Пример так
Да, я уже заметил что-то неладное с UTFT и с созданием элемента класса "myGLCD" в строке:
Там явно создаётся еще одна переменная и только она потом вызывается через точку со всеми другими элементами UTFT. Я так делал - ничего не вышло почему-то ((( А почему?
Начало темы, первый пост:
Добрый всем вечер.
Проблема банальна: нужно вынести пользовательские функции в отдельные файлы или файл. Чем больше читаю о создании классов или библиотек, тем больше убеждаюсь что это либо слишком сложно для меня либо вообще неприемлемо.
Вся беда в том, что мне нужно производить некоторые действия с помощью элементов библиотеки UTFT. Создаю свой класс, но он не проходит компиляцию, потому что в нем используются элементы другого класса.
Так что, получается что эта затея обречена? Вот коды моих изысков:
1. Сам скетч:
2. Заголовок "user.h":
3. Класс "user.cpp":
Я хочу знать только одно: можно ли внутри своего класса использовать элементы другого?
----------------------
Ну, собственно, часть ошибок уже исправлена, спасибо Евгению: объявлены переменные:
Исправлен вызов:
На данном этапе мне и такого положения вещей хватит, но умные советы слушать готов всегда.
Поверьте - редко кому удается с нуля взять и лупануть собственный класс, учтя все подводные камни. А вы еще и на достаточно сложном примере начали экспериментировать.
P.S. Для простых вещей (экспериментов) не стоит мучать сразу Arduino IDE с ее специфическими операторами. Я, к примеру, не завязанные на железе вещи, вообще в CodeLite сначала делаю. Там и дебаг есть и всё такое. А компилятор точно такой же, как в Arduino IDE. Так что при переносе возникает минимум проблем.
Вот именно разбивать код - это то что мне нужно, что бы не листать метры скетча.
Со структурами - хотелось бы попробовать, но что это такое и нужно ли сейчас - надо почитать...
Сложность примера обуславливалась необходимостью выделить в отдельный файл несколько функций, которые используют в свою очередь класс "myGLCD". О том что это сложно я вчера еще не догадывался ))))
Дело в том, что для меня язык Си открывается только в виде Arduino IDE, где я с ним столкнулся первый раз в жизни. Так что мне пока что сравнивать не с чем )))))) Но все равно - спасибо за советы!
Так, я буду собираться на работу. Если там комп не откинется - вечерком продолжим.
Дело в том, что для меня язык Си открывается только в виде Arduino IDE, где я с ним столкнулся первый раз в жизни. Так что мне пока что сравнивать не с чем )))))) Но все равно - спасибо за советы!
А вот это очень напрасно.
По собственному опыту: для того, чтобы сделать что-то вменяемое на Ардуино, требуется гораздо больше кода написать для ПК.
В качестве примера скажу что для проекта: http://arduino.ru/forum/proekty/floppy-hdd-music
На ПК были написаны:
1. Рабор MIDI-файла.
2. Аранжировка разобранного в п.1. под особенности конкретного инструмента.
3. Таблицы перевода нот в коэффициенты деления.
В общем, из 9 используемых файлов 7 были сгенерены в автоматическом режиме на ПК.
Это всё чудесно и проект впечатляющий. Однако. Однако же это всё хорошо для тех, кто в свободно сях разбирается и может посты на форуме писать на С++. Но Вы же тоже с чего-то начинали? Не родились же Вы с компилятором в голове?
Не родились же Вы с компилятором в голове?
я родился с if() {} в голове - следующий вопрос, пожалуйста.
И как живётся с управляющим оператором в голове? Наверно все управляют кому не лень, ставят свои условия постоянно? Мне так больше по душе switch - case: сделал что полагается и пошли все остальные нафиг со своими условиями )))
И как живётся с управляющим оператором в голове? Наверно все управляют кому не лень, ставят свои условия постоянно?
это называется управляющим оператором?
Не родились же Вы с компилятором в голове?
Ко мне внук, постоянно бегал с простейшими проблемами, которые вполне мог бы решить сам. Каждый раз я специально тратил больше времени, чем было необходимо для объяснения его проблемы специально для того, чтобы показать ему ход рассуждений и проверок от того, что он знает к решению проблемы, показывая тем самым, что он мог бы и сам это решить. Но впечатления не производило. Потом я как-то случайно брякнул, "Блин, ну вот правда, странно слышать о таких проблемах от программиста в чётвёртом поколении!". И это подействовало! Он стал гораздо больше разбираться сам и намного реже приходить с простейшими вопросами. Уж не знаю, с чем он родился, но осознав свою "наследственность", резко изменил своё отношение и это тут же сказалось на результатах. Вот такая история.
Однако же это всё хорошо для тех, кто в свободно сях разбирается и может посты на форуме писать на С++. Но Вы же тоже с чего-то начинали?
Лично я начиналс Алгола-60. Потом был Фортран...
А специально для того, чтобы научить сына программировать, выучил Паскаль.
Это я к тому, что Си для меня язык не родной и программирую я на нем недавно.
PS. навеяно постом ЕП: Buzzer2010, будем надеяться, у Вашего правнука не будет проблем с программированием.
Он стал гораздо больше разбираться сам и намного реже приходить с простейшими вопросами. Уж не знаю, с чем он родился, но осознав свою "наследственность", резко изменил своё отношение и это тут же сказалось на результатах. Вот такая история.
Может нашёл более сговорчивого деда или подсел на футбол?
Это всё чудесно и проект впечатляющий. Однако. Однако же это всё хорошо для тех, кто в свободно сях разбирается и может посты на форуме писать на С++. Но Вы же тоже с чего-то начинали? Не родились же Вы с компилятором в голове?
Есть такая штука, как скальпель (бритва) Оккама. Не знакомы? Советую.
В конечном счете все эти ваши классы превратятся в линейный код для МК. А ООП тут - исключительно синтаксический сахар, а не жизненная необходимость. Честно говоря - для проектов на ардуине за пять лет мне класс понадобился только один раз и то, думаю, что можно было избежать его использования. Я не думаю, что у вас на данный момент настолько сложный код, в котором позарез нужна функциональность классов. Но, если хочется понять, как это работает, то пожалуйста, конечно. Однако, повторюсь, что изучение принципов работы сложных структур языка без отладчика, с нуль-пространственным прыжком через все базовые вещи, является чистой воды мазохизмом.
Может нашёл более сговорчивого деда или подсел на футбол?
Второй дед у него, к сожаленю, уже умер. Из живых программистов у него прадед, я, моя жена и оба родителя (как раз он - в четвёртом поколении). Насчёт футбола - не думаю, телевизора у них в доме нет, а живые матчи в нашей деревне не проводятся.
для проектов на ардуине за пять лет мне класс понадобился только один раз и то, думаю, что можно было избежать его использования.
Избежать-то можно всегда. В конце концов, всё можно запрограммировать на
брейнфакемашине Тьюринга. Но иногда, до чего ж удобно! Вот не так давно проектик был - ардуиновская классика: радиоприёмник, совмещённый с часами, погодной станцией, лабораторным блоком питания и мультиметром (усё в одном ящике). На всё про всё один 4" семисегментный дисплей на котором надо показывать то время, то частоту радиостанции, то прогноз температуры на завтра, то напряжение или ток для мультиметра, то установку таймера, то будильника, ... и до хрена чего ещё. Иерархия классов экрана со множетсвенным наследованием настолько упростила задачу отображения информации, что диву даёшься. Без наследования трахаться там и трахаться.Честно говоря - для проектов на ардуине за пять лет мне класс понадобился только один раз и то, думаю, что можно было избежать его использования.
Правильно ли я понял, что Вы ни разу не подключали ни одной библиотеки, а классом Serial воспользовались лишь однажды, да и то по недоразумению?
Честно говоря - для проектов на ардуине за пять лет мне класс понадобился только один раз и то, думаю, что можно было избежать его использования.
Правильно ли я понял, что Вы ни разу не подключали ни одной библиотеки, а классом Serial воспользовались лишь однажды, да и то по недоразумению?
Вроде бы речь идет о пользовательском классе, а не "вообще".
Так-то я, конечно, не извращенец, если вы это хотите выяснить - на асме не пишу, но порой приходится чужие библиотеки потрошить и секвестировать, проводя, так сказать, классовую борьбу )) И не нужно сразу считать меня оголтелым тупоконечником. Если человек умеет обращаться с инструментом - пусть использует. Если не умеет - изучает, а потом сам принимает решение по поводу инструмента для решения задачи забивания гвоздя в табуретку - микроскоп брать или молотком шибануть.
Вчера, к слову, немного читал avr-lib в оригинале - тоже классов не нашёл. Так что бессмысленный философский диспут о том, является ли какая-либо подключаемая библиотека носителем класса, можно считать открытым. Участвовать в нем, правда, не обещаю.
микроскоп брать или молотком шибануть.
Не наши методы!
По-нашему - железка от молотка, планетарная передача, серво-мотор, ардуина, немного говна и палок и, опционально, потенциометр для регулировки частоты ударов - полгода траха со скетчем и имеем автоматический молоток! Во как!
Вроде бы речь идет о пользовательском классе, а не "вообще".
Что такое "класс Си++" я имею некоторое представление. А что такое "пользовательский класс"? И чем он отличается от "класса Си++"?
Так-то я, конечно, не извращенец, если вы это хотите выяснить - на асме не пишу,
Ни в коей мере не собирался переходить на личности. Вопрос сугубо "эхотажный" - о роли классов в концепции Ардуино.
Кстати, я иногда пишу на языке Ассемблера, это значит, что я - извращенец?
Вчера, к слову, немного читал avr-lib в оригинале - тоже классов не нашёл.
Ну, AVR - это одно, а Arduino - совершенно другое. И концепции у них совершенно различные, если не сказать, диаметрально противоположные.
В Ардуино любое периферийное устройство - объект. И это вполне осознанный и весьма целесообразный подход.
Так что бессмысленный философский диспут о том, является ли какая-либо подключаемая библиотека носителем класса, можно считать открытым. Участвовать в нем, правда, не обещаю.
Вопрос на самом деле не в классах, а в целесообразности применения ООП в том или ином случае. В той же Ардуино millis, digitalRead и т.п. являются простыми функциями, а не методами класса, но это никак не влияет на тот факт, что концепция Ардуино основана на ООП.
Наверное вам, как фаундеру платформы Arduino виднее насчет концепции. И, также возможно, что вам, как строгому последователю принципов Страуструпа, представляется что мы отговариваем человека писать на C++ без применения объектов. Однако хочу вас уверить, что это не так - пусть пишет так, как умеет. В данном случае с классами (именно классами C++, а то вдруг ещё какие с улицы притащит) он не умеет. Но я не совсем понимаю для чего затевать холивары на предмет Procedural vs Object-oriented в применении к Arduino. Как будто тут темы фонтанов и костылей не хватает для бессмысленного изведения траффика.
Ну народ. Я-таки обязан внести некоторую ясность. Классом свою задачу я называю только потому что этот термин используется в языке С++ и может быть в каких-то других еще, не знаю. А я и не подозревал на самом деле, что затеял такую сложную для себя головоломку. Спасибо Евгению за разъяснения и жаль что мне не довелось побыть его студентом.
Про бритву Оккама слышал в сериале Доктор Хаус. В данном контексте метод Оккама немного тернистый путь для изучения принципов грамотного программирования )))) Хотя, признаться, этим я сейчас и занимаюсь: отбразываю все неверные решения и ищу оставшиеся, которые и будут верными. Но слава Богу - есть этот форум с массой людей на порядок умнее и опытнее меня!
Другое дело, если вы эти описания шрифтов (всех) поемстите в user.h, то Вам их не нужно будет описывать ни в основном скетче, ни в user.cpp - они будут в одном месте и это правильно.
Что-то не получается пока что. После описания всех используемых шрифтов в "user.h" компилятор пишет вот что:
А вот так - работает вроде:
Кстати у меня есть сомнения насчёт строки №2 в "user.cpp"
Эту строку я собизъянничал в "UTFT.cpp" Прокомментируйте пожалуста.
=============================================================
У меня тут возникли некоторые вопросы.
Дилема №1. Если я помещу все свои подпрограммы в тело класса "user", то в основном скетче у меня останется только главный цикл, который будет перебирать элементы основного меню, а это всего несколько строк в структуре "switch-case". Другими словами - основная масса кода ляжет на плечи класса или классов (во избежании путаницы возможно придётся несколько иначе организовать деление на отдельные файлы и их может быть несколько).
Сам вопрос: насколько это корректно и правильно с точки зрения оптимизации кода?
Дилема №2. Если все мои основные циклы будут крутиться в классе, то мне придётся из одного метода класса вызывать другой и отсюда второй вопрос на ту же тему: насколько это правильно и корректно?
Спасибо.
Наверное вам, как фаундеру платформы Arduino виднее насчет концепции.
Вы всерьез полагаете, что знать, в какой цвет выкрашен забор, может только человек, который его собственноручно красил?
Как будто тут темы фонтанов и костылей не хватает для бессмысленного изведения траффика.
[ушёл создавать биржу фьючерсного трафика флуда]
1.В файлах .c/.cpp для поддержки типов данных uint8_t, int64_t и т.п. требуется производить подключение системной библиотеки stdint.h, компиляция же .ino происходит по несколько иным правилам, тут разработчики IDE подложили свинью пользователям (или облегчили им жизнь. сложно сказать) - подключение части библиотек производится после того, как вы нажали кнопку "Скомпилировать", перед фактическим вызовом компилятора.
2. Никакой существенной оптимизации, подозреваю, класс вам не принесет, но вполне может вызвать головную боль. Вы можете представить себе класс, как оглавление книги. Он помогает пользователью более удобно сгруппировать имена переменных, подпрограмм (методов класса) и таскать их потом по всему проекту, передавая в функции и т.п. Специфические свойства класса(protected-члены, например), вы не используете. Так что, фактически, делаете обычные переменные и обычные функции (компилятор будет рассматривать их именно так), но пытаетесь запихнуть их в класс потому что считаете, что так круче. Однако, в switch() вы точно так же можете вызывать подпрограммы, просто вынесенные в другой файл.
Поэтому, на самом деле, дилемма стоит перед нами - объяснять ли как собрать бензопилу для того, чтобы вы смогли из куста ивняка сделать одно удилище.
Кстати у меня есть сомнения насчёт строки №2 в "user.cpp"
#include "user.h" user::user() {}Эту строку я собизъянничал в "UTFT.cpp" Прокомментируйте пожалуста.
А тут нечего комментировать (как исполняемый, так и инициализирующий код отсутствуют)
=============================================================
У меня тут возникли некоторые вопросы.
Дилема №1. Если я помещу все свои подпрограммы в тело класса "user", то в основном скетче у меня останется только главный цикл, который будет перебирать элементы основного меню, а это всего несколько строк в структуре "switch-case". Другими словами - основная масса кода ляжет на плечи класса или классов (во избежании путаницы возможно придётся несколько иначе организовать деление на отдельные файлы и их может быть несколько).
Сам вопрос: насколько это корректно и правильно с точки зрения оптимизации кода?
Оптимизации - по какому критерию?
Идея ООП - оптимизировать труд программиста:
- чтобы он не писал по много раз одни и те же конструкции в разных проектах,
- чтобы лучше обозначить структуру программы, сгруппировав функции, имеющие отношение к одной сущности, в одном классе.
Т.е. если в проекте есть несколько взаимодействующих устройств (например, датчик и дисплей), то все взаимодействие с каждым из них помещается в соответствующий класс, а в основной программе - только связь между ними, т.е. "взять число из датчика" и "вывести число на экран".
Дилема №2. Если все мои основные циклы будут крутиться в классе, то мне придётся из одного метода класса вызывать другой и отсюда второй вопрос на ту же тему: насколько это правильно и корректно?
Спасибо.
Это совершенно нормальная ситация. Более того, обычно среди методов класса встречаются private, т.е. те, которые вызываются только из других методов класса и не могут быть вызваны извне.
Я всерьез полагаю, что о принципе выбора краски (не только ее цвета, но и физико-химико-экономических свойств), которой выкрашен забор, может знать только тот, кто придумал его покрасить. Все остальные находятся в области высказывания догадок и построения на них собственных теорий, которые, безусловно, могут многократно превосходить первоначальный замысел.
Хотя, если вы можете узнавать о концепции по одному только цвету краски - снимаю шляпу и причисляю к пантеону, который вы сами себе можете выбрать.
Я всерьез полагаю, что о принципе выбора краски (не только ее цвета, но и физико-химико-экономических свойств), которой выкрашен забор, может знать только тот, кто придумал его покрасить.
А я почему-то считал, что в первую очередь тот, кто разработал/произвел эту краску.
А тот, кто с кисточкой в руках, может вообще иметь весьма смутные представление о физике, химии и экономике.
Хотя, если вы можете узнавать о концепции по одному только цвету краски - снимаю шляпу и причисляю к пантеону, который вы сами себе можете выбрать.
Концепция - достаточно общее понятие. Поэтому с одной стороны - она не затрагивает тонкостей реализации (как то физико-химико-экономических свойства), а с другой стороны - должна быть легко понимаема не только авторами, но и широкими кругами общественности.
Другими словами: если мы видим покрашенную поверхность, то при некоторых условиях (достаточноая толщина покрытия, приемлемое освещение и отсутствие проблем со зрением) мы вполне адекватно можем судить о цвете этой краски.
Полемика это всё очень хорошо...
А вот andriano за пост #43 огромное и чисто человеческое спасибо!
Насчет критерия оптимизиции: я так понял что когда речь идёт об ардуино, критерий всегда один - скорость и возможно меньший объём прошивки. Другими словами - если от внедрения классов пострадают эти два пункта, то придётся отказаться и лепить всё в одном скетче. Кстати такая мысль уже прозвучала здесь:ЕвгенийП пишет: ... В вашем же случае использование класса проигрывает и по памяти и по времени.sadman41 пишет: Мне кажется, что ЕвгенийП прав - классы вам пока не нужны. Просто научитесь для начала разбивать код на разные файлы. Потом поработайте со структурами (struct), поймете что есть форма и что есть содержание, как крутить полями и почему там что-то "вызывается через точку". А затем уже до классов там рукой подать.
Поверьте - редко кому удается с нуля взять и лупануть собственный класс, учтя все подводные камни. А вы еще и на достаточно сложном примере начали экспериментировать.
-----------------------
В конечном счете все эти ваши классы превратятся в линейный код для МК. А ООП тут - исключительно синтаксический сахар, а не жизненная необходимость. Честно говоря - для проектов на ардуине за пять лет мне класс понадобился только один раз и то, думаю, что можно было избежать его использования.
Насчет критерия оптимизиции: я так понял что когда речь идёт об ардуино, критерий всегда один - скорость и возможно меньший объём прошивки. Другими словами - если от внедрения классов пострадают эти два пункта, то придётся отказаться и лепить всё в одном скетче.
Основной критерий оптимизации это, как не странно , надежность и удобство использования другими людьми данной библиотеки. Если же после использования у вас в программе заведутся глюки или же даже вы через полгода не будете понимать как работает ваш скетч, то никто не будет пользоваться вашей библиотекой. Если нет покупателя, то и продавец и производитель работают даром. А на счет скорости и меньшей памяти, так она должна быть просто в разумных рамках. Если же ее всеже маговато, то мега и дуе вам в помощь.
Насчет критерия оптимизиции: я так понял что когда речь идёт об ардуино, критерий всегда один - скорость и возможно меньший объём прошивки. Другими словами - если от внедрения классов пострадают эти два пункта, то придётся отказаться и лепить всё в одном скетче.
Основной критерий оптимизации это, как не странно , надежность и удобство использования другими людьми данной библиотеки. Если же после использования у вас в программе заведутся глюки или же даже вы через полгода не будете понимать как работает ваш скетч, то никто не будет пользоваться вашей библиотекой. Если нет покупателя, то и продавец и производитель работают даром. А на счет скорости и меньшей памяти, так она должна быть просто в разумных рамках. Если же ее всеже маговато, то мега и дуе вам в помощь.
Во первых - всем не угодишь. Во вторых - "надёжность и удобство" зависят от кривости рук тех, кто ее потом будет использовать. Я не могу запретить копать своё творение всем кому не попадя и потом еще выслушивать нелестные отзывы в свой адрес насчёт надёжности и удобства использования. В третих - человек не понимающий как работает его скетч, скорее всего, не является его автором. Так что это не обо мне. В четвертых: я не собираюсь торговать своими библиотеками потому что я только еще учусь программировать и врядли мне вообще такое придёт в голову. В пятых: мега и дуэ - не панацея и я уже не уверен что мне хватит 512к для того, что я задумал (((((((.....
Насчет критерия оптимизиции: я так понял что когда речь идёт об ардуино, критерий всегда один - скорость и возможно меньший объём прошивки. Другими словами - если от внедрения классов пострадают эти два пункта, то придётся отказаться и лепить всё в одном скетче.
Отнюдь.
Понятие как скорости, так и объема кода радикальным образом зависят от конкретной задачи.
Если, например, для управления каким-либо устройством требуется точность не хуже 0.1 секунды, а Ардуина в зависимости от реализации может обеспечить точность от 0.000050 с до 0.000005 с, то для устройства нет никакой разницы, который из методов реализации Вы выберете. А вот для Вас трудоемкость реализации во втором случае может оказаться больше в те самые 10 раз, а то и больше.
Аналогично с объемом: ксли выбор между 2к и 12к, то никакой разницы с этой точки зрения нет, т.к. "оставшуюся" память Вы все равно не сможете никак использовать.
Вообще же концепция Ардуино исходит из приоритета удобства пользователя перед эффективностью. Именно поэтому использование собственного кода вместо библиотечного в большинстве случаев способно существенно увеличить производительность. Весь вопрос в том, нужно ли это в конкретном проекте.
Конкретно в этом проекте - тут еще не совсем понятно, поскольку все ветви проекта еще не осуществлены. Та часть, которая концептуально уже готова особого быстродействия не требует, поскольку считывание показаний температуры с 18B20 происходит настолько медленно, что в цикле не надо даже delay() ставить.
Насчет трудоёмкости, то если это избавит меня от других недостатков работы скетча, то я с удовольствием ее переживу. Держать в голове громадные куски исходного кода - мне не привыкать. Ну а перелистывать - труд небольшой.