Когда выполняются глобальные констукторы?

c++

Прошу прощения, если это уже обсуждалось раньше, но я ничего не смог найти.

Я написал простой класс светодиодов. Для иллюстрации (на самом деле это немного сложнее), но это звучит примерно так:

class LED {
    LED(byte pin);
  private:
    int _pin;
};

А конструктор - это просто;

LED::LED(byte pin) {
    _pin = pin;
};

и я создаю глобальный экземпляр этого класса в верхней части моего кода таким образом;

LED redLED(5);

Это необходимо создать как глобальный объект, потому что (а) я не могу создать объект в функции setup(), потому что он выйдет за рамки, и (б) я не могу создать в функции loop(), потому что я не хочу создавать бесконечное количество этих объектов.

Кажется, все это работает нормально, но мне просто интересно, когда именно этот конструктор будет выполнен? Я полагаю, что это должно быть до setup()?

Ответили!

Большое спасибо всем респондентам. Поэтому при использовании Arduino IDE процесс сборки должен молча вставить процедуру main(). Я не знал, что он это делает. Я предполагаю, что в большинстве случаев вам сойдет с рук не знать, когда вызываются глобальные конструкторы.

Хорошей практикой (я думаю) является создание класса "обертка" для всех / любых внешних (или, возможно, внутренних) аппаратных устройств, подключенных к вашему arduino. И поэтому, возможно, заманчиво (но рискованно) выполнять работу инициализации в конструкторе.

Поэтому, учитывая то, что я теперь знаю, лучше создать метод "init()" для таких классов, которые могут быть вызваны из setup() . Даже если просто сделать вызов pinmode() .

Еще раз спасибо.

, 👍2

Обсуждение

Re “_ процесс сборки должен автоматически вставлять процедуру main()_”: это [предоставляется основной библиотекой Arduino] (https://github.com/arduino/ArduinoCore-avr/blob/1.8.3/cores/arduino/main.cpp ). Re “_ лучше создать метод ‘init()'_”: казалось бы, ’begin()` - это каноническое имя для такого метода., @Edgar Bonet


3 ответа


Лучший ответ:

2

Глобальные конструкторы запускаются сразу после инициализации , выполняемой кодом запуска среды выполнения C, и непосредственно перед вызовом main() .

В двух словах, код инициализации среды выполнения C:

  • выполняет ли некоторые низкоуровневые инициализации (например, настройку памяти)
  • вызывает глобальные конструкторы
  • вызывает main(), который, в свою очередь
    • вызывает init() для выполнения инициализации, специфичной для Arduino
    • настройка вызовов()
    • многократно вызывает loop()

Мелкие детали, вероятно, зависят от конкретной платформы. Для плат на базе AVR они описаны в руководстве avr-libc.

,

0

Он выполняется до вызова main() (в main() вызывается setup(), а затем loop() вызывается в бесконечном цикле).

Он имеет свои собственные разделы для конструкторов и деструкторов: http://beefchunk.com/documentation/sys-programming/binary_formats/elf/elf_from_the_programmers_perspective/node4.html

,

0
class LED {
private:
  const byte _pin;
public: 
  LED(const byte pin);
};

С еще более простым к'тором:

LED::LED(const byte pin) : _pin(pin) {};

Чтобы быть немного по теме: список инициализаторов выполняется даже перед телом конструктора и, таким образом, является способом инициализации констант.

Остается вопрос, гарантировано ли это, что это работает:

class LED {
private:
  const byte _pin;
public;
  LED(const byte pin) : _pin(pin) {pinMode(_pin,OUTPUT);}
  set(bool state) {digitalWrite(_pin, state); }
};

(Можно ли вызвать pinMode так рано или следует изобрести метод init() ? )

Мой опыт говорит : работает хорошо ...

,

Обратите внимание, что конструктор запускается до инициализации ядра Arduino. Вы уверены, что он хорошо работает на каждой плате Arduino? В AVR это, конечно, так, потому что pinMode () не зависит от готовности ядра Arduino., @Edgar Bonet

Я тестировал это только на Нано, @Rob W