Вопрос по ООП

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

bwn пишет:

Пух, ты не поверишь, но мой любимый телефон Panasonic, был как раз с трекболом, а любимый из за того, что его раз в три дня к зарядке подключать приходилось (все остальные кажный день, а то и чаще), чисто в ждущем режиме вообще 180 часов обещали. На пенсию он ушел именно по причине окончательной смерти трекбола и отсутствия запчастей.

у телефона с текболом экран не нужно было обновлять?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Клапауций 003 пишет:

у телефона с текболом экран не нужно было обновлять?

Зачем? У него ж трекбол есть!

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

bwn пишет:

qwone пишет:

Точно. Так и есть. Конечно если питать от сети это не важно, но аккумуляторы малы по емкости и по ресурсу. Покупателю все же удобнее не подключать каждый день к зарядке. Тем более при менее мощном процессоре обгонять конкурентные модели это боллее сильное преимущество на рынке.

Пух, ты не поверишь, но мой любимый телефон Panasonic, был как раз с трекболом, а любимый из за того, что его раз в три дня к зарядке подключать приходилось (все остальные кажный день, а то и чаще), чисто в ждущем режиме вообще 180 часов обещали. На пенсию он ушел именно по причине окончательной смерти трекбола и отсутствия запчастей.

филлипс то получше будет, раз в месяц заряжать приходится )))

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Чем меньше обновляешь экран, тем дольше живет аккум. А еще лучше от греха подальше выключить телефон.

anarch
Offline
Зарегистрирован: 10.09.2017

Интересно, а зачем нужны методы begin если можно то же самое в конструкторе сделать? 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

anarch , не все в конструкторе можно сделать. А точнее в конструкторе запущенном глобально. А локально не пройдет, так как у Ардуины  две функции setup и loop.

ПС: Для неверующего Фомы попробуйте I2C без begin запустить или тот же Serial. :))

anarch
Offline
Зарегистрирован: 10.09.2017

Не совсем о том. Во многих библиотеках конструктор либо пустой либо вызывает init, begin и подобное, плюс ко всему куча сетеров, в свою очередь вызываемых из begin.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Это или мода или попытка или у класса дофига конструкторов и как-то обобщить их код и снизить повторную работу для программиста.

bwn
Offline
Зарегистрирован: 25.08.2014

Клапауций 003 пишет:

bwn пишет:

Пух, ты не поверишь, но мой любимый телефон Panasonic, был как раз с трекболом, а любимый из за того, что его раз в три дня к зарядке подключать приходилось (все остальные кажный день, а то и чаще), чисто в ждущем режиме вообще 180 часов обещали. На пенсию он ушел именно по причине окончательной смерти трекбола и отсутствия запчастей.

у телефона с текболом экран не нужно было обновлять?

Клапочка, я этого не говорил, там предыстория есть, почему не ставят мыша али трекбола.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

А я что то думал, что самым жрущим батарею в мобильных устройствах элементом было (и, наверное, остаётся) - подсветка экрана. 

Сколько раз замечал - если подсветка на минимуме, так и живет без подзаряда раза в три-четыре дольше, чем с подсветкой «на всю катушку». 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Ну на современных экранах чистой подсветки давно нет. И да посмотрите расход энергии на статичной картинке или когда идет видео. Вот когда идет видео, то уже "подсветка" жрет немного. Можно конечно сказать что обработка видеофайка это не обновление экрана. Но здесь перепутана причина и следствие. Что бы посмотреть нормально фильм то надо часто обновлять картинки, а что бы получить новые картинки нужно обработать видеофайлы. По факту уже расход энергии идет не только перегонке информации из разных буферов, но и получить информацию из видеофайла в буфер.

ПС:https://www.youtube.com/watch?v=I5Zh3v841E4

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Пух, ты бредишь?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

anarch пишет:

Интересно, а зачем нужны методы begin если можно то же самое в конструкторе сделать? 

На ПК это не нужно. 

Не нужно потому, что конструктор вызывается только после того, как запустится Ваша программа, а Ваша программа запустится только после загрузки ОС.

На МК это не так: глобальные конструкторы вызываются до первого исполняемого оператора. Т.е. до настройки "железа", которая обеспечивает ардуиновский сервис - конфигурирование таймеров, настройку службы времени и т.п. Поэтому, если для инициализации класса необходимы какие-либо системные функции Ардуино, то эту инициализацию невозможно произвести в конструкторе класса и ее осуществляют в методах begin или init, вызываемых уже после первоначальной настройки железа, которая осуществляется между конструкторами объектов и вызовом функции setup().

anarch
Offline
Зарегистрирован: 10.09.2017

 

Например системные функции? Мы же подключили Arduino.h, что еще для счастья нужно?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

anarch пишет:

 

Например системные функции? Мы же подключили Arduino.h, что еще для счастья нужно?

Еще раз: в некоторых случаях необходим вполне конкретный порядок выполнения следующих операций:

1. Инициализация системного железа Ардуино.

2. Инициализация экземпляра класса.

Если требуется произвести 2 раньше 1, код инициализации класса помещается в конструктор, а если 1 должна быть раньше 2, то инициализации класса помещается в метод begin(), вызываемый из setup().

anarch
Offline
Зарегистрирован: 10.09.2017

Видимо какое то железо секретное из setup() инициализируется.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

anarch пишет:

Видимо какое то железо секретное из setup() инициализируется.

До setup можно инициализировать только то что в ОЗУ(в памяти), то с setup инициализируется аппаратная часть как МК, так и то что вешается на МК. Если вы этого не можете отличить , то и объяснять вам бесмысленно.

А по факту железо и таймеры Ардуино начинают инициализироваться  с запуском main

int main(void)
{
	init();

	initVariant();

#if defined(USBCON)
	USBDevice.attach();
#endif
	
	setup();
    
	for (;;) {
		loop();
		if (serialEventRun) serialEventRun();
	}
        
	return 0;
}

https://arduinomaster.ru/program/arduino-void-loop-i-void-setup/

anarch
Offline
Зарегистрирован: 10.09.2017

ХМ... Создаю значит класс использую в не millis(), pinMode(), digitalWrite(), и прочую лабуду. Иницаилизирую экземпляр до setup() и все работает. Что я не могу сделать без блока setup()?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

попытайтесь analogWrite()

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

anarch пишет:

ХМ... Создаю значит класс использую в не millis() .... Инициализирую экземпляр до setup() и все работает. 

Вы ошиблись - не работает. Тупо 0 возвращает.

anarch
Offline
Зарегистрирован: 10.09.2017

Да, извините ошибочка вышла ) все это я использую в методах. 

 Получается переменные и порты только можно инициализировать в конструкторе.

Клапауций 003
Offline
Зарегистрирован: 20.07.2019

ЕвгенийП пишет:

anarch пишет:

ХМ... Создаю значит класс использую в не millis() .... Инициализирую экземпляр до setup() и все работает. 

Вы ошиблись - не работает. Тупо 0 возвращает.


если возвращает, то работает.

anarch
Offline
Зарегистрирован: 10.09.2017
class Abracadabra{
 public:
 Abracadabra(){
  pinMode(3,OUTPUT);
  analogWrite(3,1);
 }
};

Abracadabra bum;

void setup() {
  // put your setup code here, to run once:
}

void loop() {
  // put your main code here, to run repeatedly:
}

Это работает )

anarch
Offline
Зарегистрирован: 10.09.2017

А как дело в ардуине обстоит с деструкторами? Смысл в ним есть? 

negavoid
Offline
Зарегистрирован: 09.07.2016

Есть конечно, ведь не все объекты классов будут статическими.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

anarch пишет:

А как дело в ардуине обстоит с деструкторами? Смысл в ним есть? 

Все знают String. Ну хотя бы те кто занимаюся больше чем поклянчить на форуме код.

Открываем https://android.googlesource.com/platform/external/arduino/+/d5790d78880d4bd60be277ee20e53a851aa8c116/hardware/arduino/cores/arduino/WString.h

строка 40

~String() { free(_buffer); _length = _capacity = 0;}     //added _length = _capacity = 0;

А чего в скетчах ардуинщиков не встречается. Так и классы для них "шозаблятьэто.."

anarch
Offline
Зарегистрирован: 10.09.2017

Короче говоря, редко но нужно.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Виишли, по традиции, в Ардуино все объекты глобальные, их жизнь заканчивается вместе с пропаданием питания, поэтому на деструкторы зачастую забивают.  Но, конечно, классы типа String, которые многократно создаются/пересоздаются нерадивыми пользователями, просто обязаны иметь деструктор.  

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

anarch пишет:

Короче говоря, редко но нужно.

Скоро без этого хозяйства уже не обойтись. Памяти больше. GUI на адуину напишут.Сенсорные панели кругом будут использовать. В общем кругом динамические объекты и мало статических.

anarch
Offline
Зарегистрирован: 10.09.2017

qwone пишет:

 GUI на адуину напишут.

Ага уже разбежались с GUI, сколько нормальную IDE не могут сделать :)

Ну а в связи с традициями где мало памяти и объект живет от включения до выключения и возник вопросик а нужен ли деструктор каждой палке. 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

anarch пишет:
Ну а в связи с традициями где мало памяти и объект живет от включения до выключения и возник вопросик а нужен ли деструктор каждой палке. 

Вот и в палеолите такой вопрос был задан. В связи с тем что веревок на всех не хватает, то надо ли привязывать камень к каждой палке или обойтись только дубинками в качестве основного оружия в войске. 

ПС: если не хотите что бы ушли вслед за питекантропами , то учитесь создавать и находить применение динамическим объектам.

negavoid
Offline
Зарегистрирован: 09.07.2016

anarch пишет:
Ага уже разбежались с GUI, сколько нормальную IDE не могут сделать :)

Нет смысла - начинающим и родной вполне достаточно, а кто хочет попродвинутее, могут писать в VS Code, а могут и в Visual Studio, с отладкой, автокомплитами там, рефакторингом, вот этим всем.

GUI для разных дисплеев уже давно куча понаписана, плюс каждый день новички лепят свои новые.

anarch
Offline
Зарегистрирован: 10.09.2017

В родной только диодом помигать добавить 2-3 переменные, чуток подкорректировать пример и ВСЕ!

Если что то писать, то с каждой строчкой хочется застрелиться.

И как раз таки нормальная IDE и нужна новичкам со всеми ее плюшками. Хотя бы потому что следит за действиями и на лету предупреждает. На форуме бы в разы уменьшилось тем "ПОМОХИТЕ мой мега блинк не работает". 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

anarch пишет:
И как раз таки нормальная IDE и нужна новичкам со всеми ее плюшками.

Да не нужны новичкам плюшки. Они даже читать не могут блин. Возьмем например Вас. Найдите здесь деструкторы. https://github.com/adafruit/Adafruit-GFX-Library/blob/master/Adafruit_GFX.h

А ведь это есть GUI под ардуино.

anarch
Offline
Зарегистрирован: 10.09.2017
~GFXcanvas1(void);
~GFXcanvas8(void);
~GFXcanvas16(void);

продолжайте ))

А кому нужны, ГУРУ? В том то и дело что плюшки всем нужны. 

Только профессионалам они увеличивают производительность, а новичков избавляют от детских ошибок.

Даже не ошибок, а от невнимательности. И подсветкой синтаксиса так сказать тыкают носом.

А не нативная среда в которой по дефолту все отключено после компиляции просто скажет "я не собрала ищи что не так". 

Вот пример того, что происходит. Если бы среда подчеркнула и по человечески вывела ошибку всем бы жить было легче.

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Мне кажется для ветки Arduino IDE Pro нашлось бы место среди середнячков. Кто уже не моргает диодами, но ещё не пишет на чистом си для контроллеров. Не?

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

anarch пишет:

~GFXcanvas1(void);
~GFXcanvas8(void);
~GFXcanvas16(void);

продолжайте ))

А кому нужны, ГУРУ? В том то и дело что плюшки всем нужны. 

Только профессионалам они увеличивают производительность, а новичков избавляют от детских ошибок.

GFXcanvas1::~GFXcanvas1(void) {
    if(buffer) free(buffer);
}
GFXcanvas8::~GFXcanvas8(void) {
    if(buffer) free(buffer);
}
GFXcanvas16::~GFXcanvas16(void) {
    if(buffer) free(buffer);
}

Не правда ли они похожи. Если вы не работаете с кучей, то деструкторы не нужны. А вот куча нужна для переработки больших объемов данных.  А плюшки это источник самоуверенности, самообмана. Что у новичков, что у профессионалов.

anarch
Offline
Зарегистрирован: 10.09.2017

Не знаю что конкретно делает данная библиотека, но осмелюсь предположить где то в конструкторе выделяется буфер под изображение а в деструкторе освобождается память. И как то это связано с обновлением изображения на экране. 

BOOM пишет:

Мне кажется для ветки Arduino IDE Pro нашлось бы место среди середнячков. Кто уже не моргает диодами, но ещё не пишет на чистом си для контроллеров. Не?

Если вы про алфа версию Arduino IDE Pro это же VS Code :)))

Уже человеческий вид приобретает. Не то что старый, добрый блокнот ))

В VS Code + PlatformIO единственное не нравится файл конфигурации проекта.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

anarch пишет:

Если бы среда подчеркнула и по человечески вывела ошибку всем бы жить было легче.

Среда-то как раз по-человечески сказала всё, что нужно, точно и однозначно, а то, что юзер не умеет читать, это как бы не её дело. Она что, должна была для не умеющих читать "видос об ошибке на ютуб выложить"?

Вообще, вопрос про деструкторы - тролльский вброс. Считаю свой пост (который кто-то из модераторов потёр) наиболее адекватным и сутевым ответом. Надеюсь, Вы успели его прочитать, прежде, чем его потёрли.

anarch
Offline
Зарегистрирован: 10.09.2017

Успел не переживайте )

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, слава Богу, а то я уж извёлся весь.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

anarch пишет:
Не знаю что конкретно делает данная библиотека, но осмелюсь предположить где то в конструкторе выделяется буфер под изображение а в деструкторе освобождается память. И как то это связано с обновлением изображения на экране.
Прямое. Как идет мультипликация. Берется чистый лист, рисуется картинка,готовая картинка отправляется на экран, а использованный лист в мусор. И так каждый раз. Только вместо чистого листа берется объект GFXcanvas рисуется методами из Adafruit_GFX, отправляется в дисплей смотри на датащит из буфера методом getBuffer, а дальше в мусор деструктором. Бедненко с компонентами винды не сравнить,но що  маемо, то маемо. Хотите больше пишите свое.

anarch
Offline
Зарегистрирован: 10.09.2017
Оставлю это здесь, так сказать для оценки. В принципе как решение заданного вопроса в начале ветки.
#include <Arduino.h>

typedef void (*Handler)();

struct TimerNode
{
  uint32_t previous;
  uint32_t interval;
  Handler handler;
  TimerNode *pNext;
};

class EasyTimer
{
private:
  TimerNode *Head;

public:
  EasyTimer() : Head(nullptr){};
  ~EasyTimer(){};

  void add(const Handler, const uint32_t);
  void loop();
};

void EasyTimer::add(const Handler handler, const uint32_t interval)
{
  if (Head == nullptr)
  {
    Head = new TimerNode{millis(),
                         interval,
                         handler,
                         nullptr};
  }
  else
  {
    TimerNode *current = this->Head;
    while (current->pNext != nullptr)
    {
      current = current->pNext;
    }
    current->pNext = new TimerNode{millis(),
                                   interval,
                                   handler,
                                   nullptr};
  }
}

void EasyTimer::loop()
{
  TimerNode *current = this->Head;
  while (current != nullptr)
  {
    if (millis() - current->previous >= current->interval)
    {
      current->handler();
      current->previous = millis();
    }
    current = current->pNext;
  }
}

EasyTimer Timer;

void blink()
{
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}

void setup()
{
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  Timer.add(blink, 1000);
}

void loop()
{
  // put your main code here, to run repeatedly:
  Timer.loop();
}
DATA:    [          ]   1.0% (used 21 bytes from 2048 bytes)
PROGRAM: [=         ]   5.5% (used 1784 bytes from 32256 bytes)
qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

1-#165

2- Можно добавить лямду

typedef void (*Handler)();
struct TimerNode {
  uint32_t previous;
  uint32_t interval;
  Handler handler;
  TimerNode *pNext;
};

class EasyTimer
{
  private:
    TimerNode *Head;

  public:
    EasyTimer() : Head(nullptr) {};
    ~EasyTimer() {};
    void add(const Handler, const uint32_t);
    void loop();
};

void EasyTimer::add(const Handler handler, const uint32_t interval) {
  if (Head == nullptr) {
    Head = new TimerNode{millis(),
                         interval,
                         handler,
                         nullptr};
  }
  else
  {
    TimerNode *current = this->Head;
    while (current->pNext != nullptr)
    {
      current = current->pNext;
    }
    current->pNext = new TimerNode{millis(),
                                   interval,
                                   handler,
                                   nullptr};
  }
}

void EasyTimer::loop() {
  TimerNode *current = this->Head;
  while (current != nullptr)
  {
    if (millis() - current->previous >= current->interval) {
      current->handler();
      current->previous = millis();
    }
    current = current->pNext;
  }
}

EasyTimer Timer;
void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  Timer.add(
  /*лямда функция*/[]() {
    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  },
  /*период*/500);
}
void loop() {
  Timer.loop();
}

3 деструктор организован криво

4 у деда семена аналогичная штука есть .

anarch
Offline
Зарегистрирован: 10.09.2017

1.1 Для чего разыменовывать указатель на структуру? 

1.2 Немного не въезжаю в использование структуры. Я пишу так (наверное не правильно, но почему то работает)

struct A
{
    int a;
    A *pN;
};

не использую struct перед A *pN. В литературе написано что нужно использовать typedef. 

typedef struct A
{
    int a;
    A *pN;
};

2. Про лямбду в курсе. Кстати вы с ней и подсказали в другой ветке ;) за что огромное спасибо! 

3. Деструктор сначала написал затем удалил.

EasyTimer::~EasyTimer()
{
  while (Head != nullptr)
  {
    TimerNode *current = Head;
    Head = current->pNext;
    delete current;
  }
}

Хотя в нем большого смысла не вижу потому что планирую использовать по типу Serial.

4.Видимо у многих есть что то подобное. Все это пишу пока что в целях обучения. Полученный материал пытаюсь применить на практике.  

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

1 Структуры со ссылками на себя https://cpp.com.ru/kr_cbook/ch6kr.html#p65  считайте это тоже важный кусок знаний.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

anarch пишет:
3. Деструктор сначала написал затем удалил.

EasyTimer::~EasyTimer()
{
  while (Head != nullptr)
  {
    TimerNode *current = Head;
    Head = current->pNext;
    delete current;
  }
}

Правильно. Такое не нужно было писать, а если уж написано - то поганой метлой выметать.

anarch
Offline
Зарегистрирован: 10.09.2017

ЕвгенийП, признайтесь, вам конфетку выдают за понятное только вам сообщение?

qwone пишет:

1 Структуры со ссылками на себя https://cpp.com.ru/kr_cbook/ch6kr.html#p65  считайте это тоже важный кусок знаний.

Прочитал это и многое другое, но не знаю с чем это связанно, со стандартами или переводом. 

В приведенной вами ссылке указывают слово struct, а вот в книге, например Подбельского опускается данное слово.

И опять же не совсем понятно с псевдонимом. Если создали структурный тип, зачем нужен псевдоним. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

anarch пишет:

ЕвгенийП, признайтесь, вам конфетку выдают за понятное только вам сообщение?

И коньяк наливают.

anarch
Offline
Зарегистрирован: 10.09.2017

Нашел когда указывать нужно слово struct в книге "Язык программирования С++" Б.Страуструп. 

Цитата:

В силу причин, уходящих корнями глубоко в предысторию С, разрешается объявлять структуру и не структуру с одинаковыми именами в одной  той же области видимости.
struct stat { /* ... */ }
int stat ( char* name, struct stat* buf);
В этом случае простое имя (stat) есть имя не структуры, а доступ к структуре должен осуществляться с использованием ключевого слова struct. Однако лучше избегать подобной перегрузки имен.

И вообще рекомендуется использовать класс вместо структуру. Но вот оправдано ли использование вложенного класса вместо структуры?