Как инициализировать массив объектов в настройке (setup)?
Как объявить пустой глобальный массив для инициализации при настройке?
Я бы хотел сделать следующее:
#include <ResponsiveAnalogRead.h>
const size_t ANALOG_SIZE = 3;
const int ANALOG_PINS[ANALOG_SIZE] = {A0,A1,A2};
ResponsiveAnalogRead analog_reads[ANALOG_SIZE];
void setup() {
for(size_t i=0; i<ANALOG_SIZE; i++){
analog_reads[i]=ResponsiveAnalogRead(ANALOG_PINS[i], true, 0.01);
}
}
Но я получаю следующую ошибку:
sketch_may29c:5: error: no matching function for call to 'ResponsiveAnalogRead::ResponsiveAnalogRead()'
ResponsiveAnalogRead analog_reads[ANALOG_SIZE];
^
Невозможно ли объявить пустой массив заданного размера?
@RedPixel, 👍2
Обсуждение3 ответа
Лучший ответ:
Как писал Крейг, объявление массива с типом класса вызовет конструктор по умолчанию класса, который не имеет аргументов. Класс, который вы используете, не предоставляет конструктор по умолчанию, так как ему нужны его параметры. Вы не можете сделать это таким образом.
Но вы можете использовать динамическое выделение. В глобальной области видимости объявите только массив указателей на объекты ResponsiveAnalogRead
:
ResponsiveAnalogRead *analog_reads[ANALOG_SIZE];
Этот массив содержит только указатели, которые могут указывать на объекты ResponsiveAnalogRead
. Сами объекты еще не созданы. В setup()
вы можете затем динамически создать объекты с помощью оператора new
:
analog_reads[0] = new ResonsiveAnalogRead( input_parameters);
(Разумеется, вам придется заменить input_parameters
на все параметры, которые нужны конструктору). Чтобы вызвать член объекта, вы можете разыменовать его следующим образом:
analog_reads[0]->member_function();
Если вы еще не знакомы с указателями, вам следует поискать в Google обучающие материалы (их много), чтобы понять принцип, лежащий в их основе.
Важное примечание: Динамическое выделение памяти записывается в кучу в ОЗУ. Поскольку Arduino (особенно на базе Atmega) имеет очень ограниченный объем ОЗУ, с динамическим выделением следует обращаться с большой осторожностью. Вам не следует часто создавать и удалять данные в вашей программе, так как это сделает вашу кучу сыром. Но выделение памяти в вашей программе только один раз и ее постоянное удаление не будет проблемой, если вы не попытаетесь выделить слишком много памяти.
Когда вы объявляете массив, он вызывает конструктор по умолчанию для типа. ResponsiveAnalogRead не имеет конструктора по умолчанию, поэтому он не может инициализировать записи в массиве.
Крейг уже объяснил, что причина ошибки — отсутствие значения по умолчанию. конструктор, и chrisl предложил разумную альтернативу. Я бы хотел предложить две другие альтернативы.
Статическая инициализация
Вы заявляете, что хотите выполнить инициализацию в setup()
, но вы
не объясняй зачем ты этого хочешь. Я угадаю, что ты действительно
хотим иметь все эти объекты в массиве. Страница библиотеки предоставляет
этот пример показывает, как статически инициализировать несколько экземпляров:
ResponsiveAnalogRead analogOne(A1, true);
ResponsiveAnalogRead analogTwo(A2, true);
Проблема этого примера в том, что у вас нет массива, поэтому вы не может перебрать экземпляры. Однако эта проблема может быть легко решена исправлено:
const size_t ANALOG_SIZE = 3;
ResponsiveAnalogRead analog_reads[ANALOG_SIZE] = {
ResponsiveAnalogRead(A0, true),
ResponsiveAnalogRead(A1, true),
ResponsiveAnalogRead(A2, true)
};
Обратите внимание, что вам больше не нужен массив ANALOG_PINS
. И вам не нужно
необходимо передать 0.01
в качестве последнего аргумента конструктора, так как это
значение по умолчанию в любом случае. Это было бы моим предпочтительным решением: это
достаточно просто и не увеличивает количество строк кода.
Исправление библиотеки
Если вы действительно хотите инициализировать массив в setup()
, то вы можете
Исправьте файл ResponsiveAnalogRead.h из библиотеки:
- Добавьте значения по умолчанию для всех параметров конструктора. Для пример:
ResponsiveAnalogRead(int pin=0, bool sleepEnable=0, float snapMultiplier=0.01);
- Добавьте метод установки пина после инициализации:
ResponsiveAnalogRead(int pin=0, bool sleepEnable=0, float snapMultiplier=0.01);
Первое изменение позволит вам компилировать ваш код как есть. Второе
изменение позволит вам обновить объекты в setup()
вместо
перезаписывая их (что я не нахожу очень элегантным):
void setPin(int newPin) { pin = newPin; pinMode(pin, INPUT); }
Обратите внимание, что использование конструктора по умолчанию теперь имеет побочный эффект
установка контакта 0 на вход. Это не должно быть большой проблемой, так как
конструктор вызывается до setup()
, и все контакты ввода-вывода являются входами
на этом этапе. Если вы все же хотите отменить этот побочный эффект, то
установите пин по умолчанию на -1
и исправьте конструктор так, чтобы он настраивал только
пин-код, если он не -1
.
Однако исправление библиотеки создает дополнительную нагрузку по обслуживанию: вам придется
повторно применять патч каждый раз при обновлении библиотеки. Это может быть не
это плохо, если вы знаете, как git rebase
или git merge
, но в идеале вы
хотелось бы, чтобы запрос на извлечение был принят первоначальным сопровождающим.
Изменить: Перед исправлением библиотеки рассмотрите возможность добавления этого проблема и использование этого форка.
Обновление: запрос на извлечение, решающий эту проблему, был отправлен принято. Начиная с версии 1.2.0, класс теперь имеет значение по умолчанию «ничего не делать» конструктор.
Спасибо за еще более развернутый ответ!
Кстати, причина, по которой я хочу инициализировать в setup(), заключается в том, что я хочу мультиплексировать эти аналоговые выводы на 16 каналов. Я хочу, чтобы каждый мультиплексированный канал имел свой собственный объект ResponsiveAnalogRead. Это также означает, что я не хочу избавляться от массива ANALOG_PINS
, потому что я хочу пройти по нему 16 раз :) Я думал о том, чтобы исправить библиотеку после ответа @Craig, но у меня нет опыта работы с C++. Спасибо за предложение проблемы и форка, но я уже воспользовался решением, предложенным @chrisl., @RedPixel
- Возможно ли иметь массив массивов int?
- Замена нескольких выводов pinMode() и digitalWrite() на массив
- Ошибка: invalid application of 'sizeof' to incomplete type 'int []' при попытке вычислить размер массива в библиотеке
- Инициализация массива структур
- Невозможно создать массив типа const char*
- Как изменить байт на целое число? - Arduino
- Работает ли конструкция int array[100] = {0} на Arduino?
- Как найти индекс максимального значения в массиве?
Вы пробовали пример скетча, который идет в комплекте с библиотекой?, @jsotola
@jsotola да, это прекрасно компилируется, но использует только один объект ResponsiveAnalogRead. https://github.com/dxinteractive/ResponsiveAnalogRead также показывает, как использовать несколько выводов, но инициализирует их глобально, а не при настройке. Я хочу выполнить цикл по массиву номеров выводов, чтобы инициализировать несколько из них., @RedPixel