Если нужна пакетная обработка, то лучше setup и loop сделать статическим методом. А городить с абстракными и виртуальными. Так это надо сначало написать новую среду разработки программ на Винде , и потом эта среда будет уже программировать абстрактные классы.
Да qwone, то архитектура не того гарварда, то винду дописывать, то статически лучше но потом. Пишите проще "гранаты не той системы", мы поймем ;)
Бабы в таких случаях говорят "проще дать чем обяснить чего нет". Вижу проще самому написать, чем обяснить почему.
Код. Проверен. Смотрим сириал и наслаждаемся. Саму музыку в Cl_music и кнопку в Cl_Btn сами прицепите. У меня они не припаяны.
class Arduiner
{
public:
virtual void setup()=0;
virtual void loop()=0;
};
class Cl_Btn : public Arduiner
{
void setup() { Serial.println("Cl_Btn.setup"); }
void loop() { Serial.println("Cl_Btn.loop"); }
};
unsigned long mill;//переменая для millis()
class Cl_delay : public Arduiner
{
unsigned long int OldMs;
unsigned long int Per;
int cnt;
protected:
void setup()
{
Serial.println("Cl_delay.setup");
Per=0 ;
cnt=0;
}
private:
void loop()
{
Serial.println("Cl_delay.loop");
if(mill-OldMs>Per)
{
OldMs=mill;
Per=Timer(cnt++);
}
}
public:
virtual unsigned long int Timer(int step)=0;
};
class Cl_music : public Cl_delay
{
void setup() {
Serial.println("Cl_music.setup");
Cl_delay::setup();
}
unsigned long int Timer(int step)
{
Serial.println("***Cl_music.tone");
return 200; //сколько мсек до следующего вызова этой функции
}
};
class Cl_blim : public Cl_delay
{
int t;
unsigned long int Timer(int step)
{
Serial.println("***Cl_blim.tone");
digitalWrite(13, step&1);
return t;
}
public:
Cl_blim(int p){t=p;};
};
Cl_Btn Btn;
Cl_music music;
Cl_blim blim(300);
Arduiner* Obj[]={&Btn, &music, &blim};
#define ALL_OBJ(a) for(byte i=0;i<sizeof(Obj)/sizeof(Obj[0]);i++){Obj[i]->a;};
void setup()
{
Serial.begin(9600);
ALL_OBJ(setup());
}
void loop()
{
mill = millis();
ALL_OBJ(loop());
delay(50);
}
ПС. Такая работа с классами - вобщем все что нужно знать ардуинщику о ООП. Для джуниора умение писать такое - необходимый минимум для допуска к собеседованию по С++.
Есть такой модуль на MAX7219.Ну и я написал скетч. Сыроватый, но уже работает. Осталось закинуть знакогенератор на все знаки . Можно русские или латинские. Разумеется те что можно отобразить и использовать в проектах. Вот код
/**/
// ------Cl_print------------------
class Cl_print {
protected:
public:
virtual write(char obj) = 0;
void print(char *obj) {
int len = strlen(obj);
for (int i; i < len; ++i) write(obj[i]);
}
void print(int value, unsigned char base = 10) {
char buf[18];
itoa(value, buf, base);
int len = strlen(buf);
for (int i; i < len; ++i) write(buf[i]);
}
void print(unsigned int value, unsigned char base = 10) {
char buf[17];
itoa(value, buf, base);
int len = strlen(buf);
for (int i; i < len; ++i) write(buf[i]);
}
void print(long value, unsigned char base = 10) {
char buf[34];
ultoa(value, buf, base);
int len = strlen(buf);
for (int i; i < len; ++i) write(buf[i]);
}
void print(unsigned long value, unsigned char base = 10) {
char buf[33];
ultoa(value, buf, base);
int len = strlen(buf);
for (int i; i < len; ++i) write(buf[i]);
}
void print(float value, unsigned char decimalPlaces = 2) {
char buf[33];
dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
int len = strlen(buf);
for (int i; i < len; ++i) write(buf[i]);
}
void print(double value, unsigned char decimalPlaces = 2) {
char buf[33];
dtostrf(value, (decimalPlaces + 2), decimalPlaces, buf);
int len = strlen(buf);
for (int i; i < len; ++i) write(buf[i]);
}
};
//------Cl_canvas------------------
// класс полотно
class Cl_canvas: public Cl_print {
protected:
char *buff;
unsigned int len;
unsigned int pos;
public:
Cl_canvas(unsigned int len_ = 10): len(len_) {
buff = new char[len + 1];
clear();
}
~Cl_canvas() {
delete[] buff;
}
//**
virtual write(char obj) {
if (obj == 0) return;
if (pos < len) {
buff[pos] = obj;
++pos;
}
}
char read(unsigned int pos_) {
if (0 <= pos_ && pos_ < len) return buff[pos_];
else return ' ';
}
unsigned int readLen() {
return len;
}
void setPos(unsigned int pos_) {
if (0 <= pos_ && pos_ < len) pos = pos_;
else pos = len;
}
void clear() {
for (byte i = 0; i < len; ++i) buff[i] = ' ';
buff[len] = 0;
pos = 0;
}
void viev() {
Serial.println(buff);
}
};
//-------Cl_Max7219_8x7seg------------------------------------------
// класс Cl_Max7219_8x7seg 8 семисегментных индикаторов на Max7219
#define DECODEMODE_ADDR 9
#define BRIGHTNESS_ADDR 10
#define SCANLIMIT_ADDR 11
#define SHUTDOWN_ADDR 12
#define DISPLAYTEST_ADDR 15
/*функция toSing
описание конвертировать с ANSI2 в знак
ввод ansi: код в ANSI2
вывод знак
*/
// знакогенератор
const char Font[] PROGMEM = {
0x00, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, //
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, //
0x7E, 0x30, 0x6D, 0x79, 0x33, 0x5B, 0x5F, 0x70, //01234567
0x7F, 0x7B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //89abcdef
};
char toSing(byte ansi) {
if (0x20 <= ansi && ansi <= 0x3F)
return pgm_read_byte_near(Font + ansi - 0x20);
return 0x20;
}
class Cl_Max7219_8x7seg {
const byte dinPin;
const byte csPin;
const byte clkPin;
public:
Cl_canvas canvas;
/*функция Cl_Max7219_8x7seg
описание создать объект
ввод _dinPin:пин данных
_dinPin:пин CS
_dinPin:пин CLK
вывод нет
*/
Cl_Max7219_8x7seg(byte _dinPin, byte _csPin, byte _clkPin)
: dinPin(_dinPin), csPin (_csPin), clkPin (_clkPin), canvas(8) {
pinMode(dinPin, OUTPUT);
pinMode(csPin, OUTPUT);
pinMode(clkPin, OUTPUT);
digitalWrite(csPin, HIGH);
}
/*функция setup
описание инициализация экрана
ввод нет
вывод нет
*/
void setup() {
setBright(10);
transfer(DISPLAYTEST_ADDR, 0);
transfer(SCANLIMIT_ADDR, 7);
transfer(DECODEMODE_ADDR, 0);
//clear();
show();
}
/*функция setBright
описание установить яркость экрана
ввод bright:яркость 0-15
вывод нет
*/
void setBright(byte bright) {
transfer(BRIGHTNESS_ADDR, bright & 0x0F);
}
/*функция show
описание вывести буфер на экран
ввод нет
вывод нет
*/
void show() {
off();
for (byte i = 0; i < 8; ++i) {
char aaa = canvas.read(i);
transfer(8 - i, toSing(aaa));
}
on();
}
/*функция transfer
описание отправить команду
ввод com: команда
data: данные
вывод нет
*/
void transfer(byte com, byte data) {
digitalWrite(csPin, LOW);
for (byte i = 0; i < 8; ++i) {
digitalWrite(dinPin, !!(com & (0x80 >> i)));
digitalWrite(clkPin, HIGH);
digitalWrite(clkPin, LOW);
}
for (byte i = 0; i < 8; ++i) {
digitalWrite(dinPin, !!(data & (0x80 >> i)));
digitalWrite(clkPin, HIGH);
digitalWrite(clkPin, LOW);
}
digitalWrite(csPin, HIGH);
}
/*функция on
описание включить дисплей
ввод нет
вывод нет
*/
void on() {
transfer(SHUTDOWN_ADDR, 0x01);
}
/*функция off
описание выключить дисплей
ввод нет
вывод нет
*/
void off() {
transfer(SHUTDOWN_ADDR, 0x00);
}
};
//------------------------
Cl_Max7219_8x7seg ld(/*DIN*/2,/*CS*/ 3,/*CLK*/4);
//------------------------
int main() {
init();
//setup()
Serial.begin(9600);
ld.setup();
ld.canvas.setPos(2);// курсор в позицию 2
ld.canvas.print(33.8);// напечатать число 33.8
ld.canvas.viev();//отправить вид в Serial
ld.show();//отправить вид на дисплей
for (;;) {
//loop()
}
return 0;
}
/*Скетч использует 4646 байт (14%) памяти устройства. Всего доступно 32256 байт.
Глобальные переменные используют 213 байт (10%) динамической памяти, оставляя 1835 байт для локальных переменных. Максимум: 2048 байт.
*/
Разумеется использовать в классах классы удобнее. Но наличие классов Си++ увеличивает размер кода и снижает быстродействие. Так что приходится использовать такие классо-заменители. Вобщем это код для светодиода
/*namespace_Led*/
unsigned long mill;
//----------------------------------
// светодиод на пине 13 (PORTB D5)
namespace Led {
void init();
void loop();
void ON();
void OFF();
void blink(unsigned int time_);
void write(bool stat);
bool led, statBlink = 0;
unsigned long time, past = 0;
void init() {
uint8_t SREG_ = SREG;
cli();
DDRB |= (1 << 5) ; //<--при измении выводa поставить нужное
SREG = SREG_;
OFF();
}
void loop() {
if (statBlink && mill - past >= time) {
past = mill;
write(led = !led);
}
}
void ON() {
write(led = 1);
statBlink = 0;
}
void OFF() {
write(led = 0);
statBlink = 0;
}
void blink(unsigned int time_=500) {
time = time_;
statBlink = 1;
}
void write(bool stat) {
uint8_t SREG_ = SREG;
cli();
if (stat) PORTB |= 1 << 5; //<-- при измении выводa поставить нужное
else PORTB &= ~(1 << 5);//<--при измении выводa поставить нужное
SREG = SREG_;
}
}//namespace Led
//----Компоновка------------------------------
//----main------------------------------
int main() {
init();
Led::init();
Led::blink(500);
for (;;) {
mill = millis();
Led::loop();
}
return 0;
}
/*Скетч использует 626 байт (2%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 23 байт (1%) динамической памяти, оставляя 2025 байт для локальных переменных. Максимум: 2048 байт.
*/
Давно не писал в своей теме. Сейчас сделаю новый наброс. Все конечно знают blink через delay(), и разумеется blink через millis() не все. Есть еще другие варианты blink-ов. Вот я вам предлагаю ознакомится c BLINK через Менеджер задач на Ардуине. Неплохая фишка, но код не все поймут. И да он работает, проверял.
unsigned long mill; // переменная под millis()
//-----Cl_Manager---------------------------
// класс менеджер задач
struct task_t {
void (*Do)();
unsigned long past;
unsigned long time;
struct task_t *next;
};
class Cl_Manager {
protected:
struct task_t (*start) = NULL;
public:
void run() {
for (struct task_t (**iii) = &start; (*iii) != NULL; ) {
if (mill - (**iii).past >= (**iii).time) {
struct task_t (*_new) = (*iii);
(*iii) = (**iii).next;
(*_new).Do();
delete _new;
}
else iii = &((**iii).next);
}
}
void Task(void (*Do)(), unsigned long time) {
struct task_t (*_new) = new struct task_t;
(*_new).Do = Do;
(*_new).past = mill;
(*_new).time = time;
(*_new).next = start;
start = _new;
}
};
Cl_Manager Manager;
//---Компоновка-----------------------
const byte ledPin =/*пин светодиода*/13;
bool led = 0;
unsigned long time_1s = 1000;
void blinkInit() {
pinMode(ledPin, OUTPUT);
blinkRun();
}
void blinkRun() {
Manager.Task(&blinkRun, time_1s);
digitalWrite(ledPin, led = !led);
}
//---main-----------------------------
void setup() {
blinkInit();
}
void loop() {
mill = millis();
Manager.run();
}
/*Скетч использует 1588 байт (5%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 26 байт (1%) динамической памяти, оставляя 2022 байт для локальных переменных. Максимум: 2048 байт.
*/
ПС:Через Менеджер можно запустить несколько независимых задач.
unsigned long mill; // переменная под millis()
//-----Cl_Manager---------------------------
// класс менеджер задач
struct task_t {
void (*Do)();
unsigned long past;
unsigned int time;
struct task_t *next;
};
class Cl_Manager {
protected:
struct task_t (*start) = NULL;
public:
void run() {
for (struct task_t (**iii) = &start; (*iii) != NULL; ) {
if (mill - (**iii).past >= (**iii).time) {
struct task_t (*_new) = (*iii);
(*iii) = (**iii).next;
(*_new).Do();
delete _new;
}
else iii = &((**iii).next);
}
}
void Task(unsigned int time, void (*Do)()) {
struct task_t (*_new) = new struct task_t;
(*_new).Do = Do;
(*_new).past = mill;
(*_new).time = time;
(*_new).next = start;
start = _new;
}
};
Cl_Manager Manager;
//---Компоновка-----------------------
//--led
const byte ledPin =/*пин светодиода*/13;
bool led = 0;
void blinkInit() {
pinMode(ledPin, OUTPUT);
blinkRun();
}
void blinkRun() {
Manager.Task(/*через 0.3 сек*/ 300,/*сделать это*/&blinkRun);
digitalWrite(ledPin, led = !led);
}
// --serial
void serialRun() {
Manager.Task(/*через 0.5 сек*/ 500,/*сделать это*/&serialRun);
Serial.println("!!!");
}
//---main-----------------------------
void setup() {
Serial.begin(9600);
blinkInit();
serialRun();
}
void loop() {
mill = millis();
Manager.run();
}
/*Скетч использует 2610 байт (8%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 207 байт (10%) динамической памяти, оставляя 1841 байт для локальных переменных. Максимум: 2048 байт.
*/
Конечно так задумано. Но вы можете делать как угодно. Вот еще вариант программы с менеджером. В принципе на нем можно писать своеобразные программы. Вот 5 функций в цикле.
Квон застрял в пещерном веке, где баб и врагов нужно бить дубиной по голове.
В этом же достаточно перестать правителям банановой республики продавать айфончики, лексусы, французские вина и сыры. А так же покупать у них бананы. И тогда всё будет как всегда - через какое-то время бравые каптерщики продадут последние стабилизаторы, свинченные в ночи с оружия страшного возмездия. А жители этой великой республики начнут ходить за туалеткой через границу. Можете про Венесуэлу посмотреть, если не верите дидам.
Думаю, что справидливости ради нужно отметить, что digitalWrite - это больше, чем запись в порт. Это, также, защита от записи куда попало, как попало (операция атомарна), отключение PWM.
Думаю, что справидливости ради нужно отметить, что digitalWrite - это больше, чем запись в порт. Это, также, защита от записи куда попало, как попало (операция атомарна), отключение PWM.
Помимо инкапсуляции, у классов есть ещё несколько замечательных фишек, типа наследования (вкл. можественное), полиморфизма, виртуализации и т.п.
Вы же пользуетесь только инкапсуляцией, начисто игнорируя всё остальное. Это довело Вас уже до такой ручки, что в #164 Вы умудрились обыкновенные пространства имён обозвать "классозаменителями".
У обычного кухоного ножа есть куча колющих и режущих родственников. Но все равно на кухне используется кухоный нож. А как было бы прекрасно если бы кухарь чистил бы картошку , к примеру, шашкой или фламбергом. Замечательное зрелище со стороны, но почему то чистят ножиком. Это я к тому , что нах*ра это в простых скетчах.
ЕвгенийП пишет:
Помимо инкапсуляции, у классов есть ещё несколько замечательных фишек, типа наследования (вкл. можественное), полиморфизма, виртуализации и т.п.
Да ладно... кто-то еще чистит картошку ножом? Я только в лесу так делаю. А для дома есть овощечистка.
А теперь представьте себе, что вы чистите картошку овощечисткой, и уже мечтаете о жареной картошки , а вам говорят что овощечистка отстой, так как овощечистка это простой наследник кухоного ножа, а еще множественное наследование , полиморфизма, виртуализации и т.п для кухонных ножей от канадской компании которые мы продадим со скидкой.
Ну, я не знаю, что у вас там в голове творится, но овощечистка, как мне кажется - как раз и есть морфированный наследник ножа ))
Ну а кухонный комбайн это "морфированая овощечиска". Но вы же не бежите ради нее в магазин бытовой техники. А вот ЕвгенийП, требует от меня брендованных классов. Но мало того что надо их придумать отладить, написать мануалы, рецепты с помощью нее, провести рекламную компании, найти спонсора, что бы оплатить всю мою работу . И зачем мне это надо?
Я требую???? Господь с Вами, где, когда и при каких обстоятельствах я что-то от Вас требовал?
Я лишь спросил "не находите ли Вы это странным". Могли бы ответить "нет, не нахожу" и всего делов. Нет же, надо выдумать какое-то требование и яростно от него отбиваться :)))))
Нее.. виртуальные здесь не годятся ;) Я пробовал в #153 дляqwone, показать как юзать наследование с абстрактным классом. Вышло так -
qwone пишет:
Но честно сильно горомоздко.
)))
Действительно, лишние буквы в коде ))))
Хороше DetSimen понял прелесть наследования, для любительского форума - прогресс небывалый, а Вы еще виртуальные методы хотите... Это громоздко ;) Ясно ж написано - классы для чайников!
Вот, вот. Если бы для новичков на форуме, было нормой использовать классы и программировать по методичке, то да это было к месту. А так даже мои простые скетчи, в в глазах большинства как "божественное откровение". Так что такая схема програмировать это противовес "честного Си на Ардуине". Наверно к этому и пришли разработчики ПO на Ардуине, потому что заказчик платит деньги, на которые они и живут.
ПС: Я разумеется был бы не против если бы кто-то разрабатывал более прогрессивные библиотеки под Ардуино.
ППС: Считайте коды здесь просто маленькой ступенькой для новичков, которые пытаюся освоить Си++ в Ардуино.
Все привыкли к такой записи b=func(a); Но иногда возможно обратноеfunc(a)=b; Для тех кто не верит вот код
//-----------------------
int &func(int &val) {
return val;
}
//----main()-----------------
void setup() {
Serial.begin(9600);
int a = 5;
func(a) = 10;//<-- обратите на эту запись
Serial.println(a);
// выведено 10
int b = 1;
func(b) = 75;//<-- обратите на эту запись
Serial.println(b);
// выведено 75
}
void loop() {
}
/*Скетч использует 1762 байт (5%) памяти устройства. Всего доступно 30720 байт.
Глобальные переменные используют 186 байт (9%) динамической памяти, оставляя 1862 байт для локальных переменных. Максимум: 2048 байт.*/
О сколько нам открытий чудных... Уже и до ссылок докопали ;)
Просто это основа примения функции возвращающих ссылки. А дальше все это модификации и импровизации. Но лучше начинать с такого простого варианта, а не более сложных фунций. Так становится проще понять механизм.
ПС: функции возвращающие ссылки это просто переменные. И обратно. Обычные переменные это функции возвращающие ссылки, но просто встроены во внутрь среды.
А чего в нем интересного? Разве что работа с char*argv[10]; элегантная. Но на односвязном списке еще лучше былобы, и без ограничения на кол-во аргументов. И еще массив указателей вполне заменяем на массив индекса символа в строке. Просто для экономии. А так обычный код.
ПС. Я и сам не люблю проверять индексы на выход за пределы массива ;) , но в приложении принимающем в массив данные извне это очень нужно!
Читать разучились? Цитирую по буквам "работа с char*argv[10]; элегантная". Причем тут if(fbs == false) ? Кстати оно тоже без криминала. Или кто тут про превосходство if(!fbs) потрындеть захотел.
Вот и я ж про тоже :)))
Да qwone, то архитектура не того гарварда, то винду дописывать, то статически лучше но потом. Пишите проще "гранаты не той системы", мы поймем ;)
Бабы в таких случаях говорят "проще дать чем обяснить чего нет". Вижу проще самому написать, чем обяснить почему.
Код. Проверен. Смотрим сириал и наслаждаемся. Саму музыку в Cl_music и кнопку в Cl_Btn сами прицепите. У меня они не припаяны.
ПС. Такая работа с классами - вобщем все что нужно знать ардуинщику о ООП. Для джуниора умение писать такое - необходимый минимум для допуска к собеседованию по С++.
Logik, спасибо за работу. Но честно сильно горомоздко. Может потом отшлифую. Сделал разметку вашего скетча под свой стиль.
Да на здорове! :) Только в либу не спешите запихивать, весь шарм пропадет.
Вот еще один своеобразный скетч. Отправка пакета-команды от управляющего компонента к исполнительному через систему стека внутри МК
Вот еще один скетч. Попытался найти замену pinMode, digitalRead,digitalWrite внутри класса на почти тоже самое, но чуть тоньше.
Еще пара вариантов замены pinMode, digitalRead,digitalWrite .
Есть такая таблица под UNO и Nano
Ну и на основе ее скетч Blink
А классы где? Нещитова!
А классы где? Нещитова!
Даааа, а ведь всё начиналось поди с безобидного безалкогольного пива :)
Разумеется использовать в классах классы удобнее. Но наличие классов Си++ увеличивает размер кода и снижает быстродействие. Так что приходится использовать такие классо-заменители. Вобщем это код для светодиода
Это код для кнопки
А это взаимодействие 1светодиода и 3-х кнопок
ПС: Разумеется можно немного сохранить размеры убрав отключение и включение прерываний, если у вас они не используются
Давно не писал в своей теме. Сейчас сделаю новый наброс. Все конечно знают blink через delay(), и разумеется blink через millis() не все. Есть еще другие варианты blink-ов. Вот я вам предлагаю ознакомится c BLINK через Менеджер задач на Ардуине. Неплохая фишка, но код не все поймут. И да он работает, проверял.
ПС:Через Менеджер можно запустить несколько независимых задач.
61
mill = millis();
62
Manager.run();
у тебя менеджер не берёт системное время самостоятельно и приходится в лупе его постоянно кормить свежим временем - это так задумано или почему?
Конечно так задумано. Но вы можете делать как угодно. Вот еще вариант программы с менеджером. В принципе на нем можно писать своеобразные программы. Вот 5 функций в цикле.
.del
del
Квон застрял в пещерном веке, где баб и врагов нужно бить дубиной по голове.
В этом же достаточно перестать правителям банановой республики продавать айфончики, лексусы, французские вина и сыры. А так же покупать у них бананы. И тогда всё будет как всегда - через какое-то время бравые каптерщики продадут последние стабилизаторы, свинченные в ночи с оружия страшного возмездия. А жители этой великой республики начнут ходить за туалеткой через границу. Можете про Венесуэлу посмотреть, если не верите дидам.
Для тех кому мешает "программировать в Адруине digtalWrite"/
Это обычный blink
1 модификация
2 модификация
3 модификация
4 модификация
Размер получаемых скетчей одинаков. И в PROGMEM укладывать пока не буду :)
Думаю, что справидливости ради нужно отметить, что digitalWrite - это больше, чем запись в порт. Это, также, защита от записи куда попало, как попало (операция атомарна), отключение PWM.
Думаю, что справидливости ради нужно отметить, что digitalWrite - это больше, чем запись в порт. Это, также, защита от записи куда попало, как попало (операция атомарна), отключение PWM.
А что такое "модефикация"? Модификация, сделанная по последней моде? :))))))))))))
Вот программа без digtalWrite
и с digtalWrite такая же
Расжевая методичка как писать программы с классами под Ардуину. Там предложена программа написания конвейера для предметов #25
Помимо инкапсуляции, у классов есть ещё несколько замечательных фишек, типа наследования (вкл. можественное), полиморфизма, виртуализации и т.п.
Вы же пользуетесь только инкапсуляцией, начисто игнорируя всё остальное. Это довело Вас уже до такой ручки, что в #164 Вы умудрились обыкновенные пространства имён обозвать "классозаменителями".
Что-то в этом подходе не так, не находите?
У обычного кухоного ножа есть куча колющих и режущих родственников. Но все равно на кухне используется кухоный нож. А как было бы прекрасно если бы кухарь чистил бы картошку , к примеру, шашкой или фламбергом. Замечательное зрелище со стороны, но почему то чистят ножиком. Это я к тому , что нах*ра это в простых скетчах.
Да ладно... кто-то еще чистит картошку ножом? Я только в лесу так делаю. А для дома есть овощечистка.
Что "это"? Ваша инкапсуляция? Или пространства имён, которые Вы обозвали "классозаменителями"? :)
Ну, я не знаю, что у вас там в голове творится, но овощечистка, как мне кажется - как раз и есть морфированный наследник ножа ))
морфированный наследник ножа ))
:)
Ну, я не знаю, что у вас там в голове творится, но овощечистка, как мне кажется - как раз и есть морфированный наследник ножа ))
Я требую???? Господь с Вами, где, когда и при каких обстоятельствах я что-то от Вас требовал?
Я лишь спросил "не находите ли Вы это странным". Могли бы ответить "нет, не нахожу" и всего делов. Нет же, надо выдумать какое-то требование и яростно от него отбиваться :)))))
а у мня вот, на все случаи жызни есть
и всё остальные даччики от него наследуюца.
Строки 14-15 я бы делал не так, а через виртуальные функции. Расходы практичски не увеличиваются, выгод много.
Нее.. виртуальные здесь не годятся ;) Я пробовал в #153 для qwone, показать как юзать наследование с абстрактным классом. Вышло так -
Но честно сильно горомоздко.
Вот, вот. Если бы для новичков на форуме, было нормой использовать классы и программировать по методичке, то да это было к месту. А так даже мои простые скетчи, в в глазах большинства как "божественное откровение". Так что такая схема програмировать это противовес "честного Си на Ардуине". Наверно к этому и пришли разработчики ПO на Ардуине, потому что заказчик платит деньги, на которые они и живут.
ПС: Я разумеется был бы не против если бы кто-то разрабатывал более прогрессивные библиотеки под Ардуино.
ППС: Считайте коды здесь просто маленькой ступенькой для новичков, которые пытаюся освоить Си++ в Ардуино.
Все привыкли к такой записи b=func(a); Но иногда возможно обратное func(a)=b; Для тех кто не верит вот код
О сколько нам открытий чудных... Уже и до ссылок докопали ;)
ПС: функции возвращающие ссылки это просто переменные. И обратно. Обычные переменные это функции возвращающие ссылки, но просто встроены во внутрь среды.
Для тех кто не верит вот код
Верить или не верить можно в Бога, а ссылки ... при чём тут вера?
Действительно, нету ссылкам веры. Верую только в истиные указатели.
Вот еще интересный код. Попытка управлять Ардуиной как консолью. Хотя пока про управление говорить не стоит
А чего в нем интересного? Разве что работа с
char
*argv[10];
элегантная. Но на односвязном списке еще лучше былобы, и без ограничения на кол-во аргументов. И еще массив указателей вполне заменяем на массив индекса символа в строке. Просто для экономии. А так обычный код.ПС. Я и сам не люблю проверять индексы на выход за пределы массива ;) , но в приложении принимающем в массив данные извне это очень нужно!
ну вот это
47
if
(fbs ==
false
) {
48
fbs =
true
;
дааа, прямо "элегантный код" ...
Было бы ещё элегантнее, если бы в 48-ой строке false было. Я тут такое не раз встречал.
Читать разучились? Цитирую по буквам "работа с
char
*argv[10];
элегантная". Причем тутif
(fbs ==
false
)
? Кстати оно тоже без криминала. Или кто тут про превосходствоif
(!fbs
)
потрындеть захотел.так отрабатываю "новые механизмы"