Сделать компонент класса ссылкой на массив

egor1855
Offline
Зарегистрирован: 24.10.2016

Для того, чтобы напрямую работать с "внешней" переменной (в данном примере массив out_pins) в качестве аргумента функции мы передаем ссылку на начало переменной

void pinController::SetPinOn(byte (&out_pins)[PINS_OUT_COUNT])

А вот как сделать такой массив компонентом класса ?

Строка вида:

class pinController
{
  public: (&out_pins)[PINS_OUT_COUNT];

Работать не будет.

Какой в данном случае должен быть синтаксис ?

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

http://arduino.ru/forum/programmirovanie/klassy-arduino-po-qwone-dlya-chainikov

Ну отсюда и далее -Операция []. Запись a[b] всегда эквивалентна *(a + b) (напомню, что мы не рассматриваем переопределения operator[] и других операций)...

ПС: И в Си лучше использовать указатели, потом создавать в куче аналог массива. 

char *massiv;// это указатель
massiv = new char[10];// это массив из 10 элементов char;
massiv[0]='a'; // занести в 1 элемент массива 'a'
massiv[1]='b';
massiv[2]='c';
massiv[3]='d';
massiv[4]='e';
massiv[5]='f';

 

egor1855
Offline
Зарегистрирован: 24.10.2016

qwone пишет:

Ну отсюда и далее -Операция []. Запись a[b] всегда эквивалентна *(a + b) (напомню, что мы не рассматриваем переопределения operator[] и других операций)...

Вот мне нужно обратное,  а именно:

char *massiv;
char *massiv1;
&massiv1 = &massiv; (для понимания сути, компилятор конечно даст ошибку)

Т.е. в инициализации объекта класса должно быть что-то вроде :

char *massiv;// это указатель
massiv = new char[10];// это массив из 10 элементов char;
//Это не код, это смысл того что я хочу сделать, но не знаю как записать синтаксически
&massiv[0]=(&massiv1);
&massiv[1]=(&massiv1+1);
...

 

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

Опять вы все перепутали. Есть ссылки , а есть указатели. Есть команда объявления указателя, а есть разыменование. В общем читате БИБЛИЮ http://cpp.com.ru/kr_cbook/ch5kr.html

int aaa;// это переменная
int *pnt;// это указатель
pnt=&aaa;// это указателю присвоили адресс на переменую
*pnt= 10;// это перемненой aaa присвоили значение 10;
int bb=*pnt; // это эквивалент bb=aaa;
так же и массивами
int mm[10];
mm[3]=*pnt; // это эквивалент mm[3]=aaa;
pnt =&mm[3]; // указатель теперь на mm[3]

 

egor1855
Offline
Зарегистрирован: 24.10.2016

Ок, спасибо.  Вот так шикарно для понимания )

egor1855
Offline
Зарегистрирован: 24.10.2016

Вот такой ещё момент :

int bb=*pnt; // это эквивалент bb=aaa;

Вопрос: При этом получили:

1.bb и aaa имеют одинаковый адрес (фактически одна переменная)

или

2.по адресу содержимого переменной bb записали значение переменной aaa ? (фактически две разных переменнных с одинаковым значением)

egor1855
Offline
Зарегистрирован: 24.10.2016

Дополнительный вопрос : фактически  указатель (в памяти) - это такая же переменная, как и все остальные ?

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

указатель (в памяти) - это такая же переменная, как и все остальные.

 

int a;  - целое

int b;  - целое

int *address;  - адрес переменной, которая хранит в себе целое

address = &a;  - address теперь хранит адрес переменной a

*address = 5;  - кабутто а=5

address = &b;  - address теперь содержит адрес переменной b

*address = a;  теперь значение b == 5;  то же самое, кабутто b=a;

без звездочки это адрес, со звездочкой - значение по этому адресу. 

 

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

egor1855 пишет:

Дополнительный вопрос : фактически  указатель (в памяти) - это такая же переменная, как и все остальные ?

Что такое переменная ? Это место в памяти куда записывают значания. Указатель это место в памяти куда записывают адресс места памяти по которому можно записисать или считать данные. Разумеется есть и такое явление указатель на указатель. Ну и так далее.  Вообще программирование на языках высокого уровня это подмена понятий. На компьютере есть только память организованая в виде ячеек памяти с адресами и все. Запись int a;  выделить ячейку памяти int.  Так a это тоже указатель, но не доступный пользовотелю. Но в Си выкрутились из этого . int *pnt=&a; И теперь у нас есть адресс на эту ячейку. Можно записать и так int &b=a; но здесь мы не получили адресс на эту ячейку. Мы просто получили еще одно название этой ячейки, а адресс на эту ячейку осталься не доступным.

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

egor1855 пишет:

Для того, чтобы напрямую работать с "внешней" переменной (в данном примере массив out_pins) в качестве аргумента функции мы передаем ссылку на начало переменной

void pinController::SetPinOn(byte (&out_pins)[PINS_OUT_COUNT])

А вот как сделать такой массив компонентом класса ?

Строка вида:

class pinController
{
  public: (&out_pins)[PINS_OUT_COUNT];

Работать не будет.

Какой в данном случае должен быть синтаксис ?

Главный вопрос: зачем?

Зачем сделать такой(внешний) массив компонентом класса?

(замечу что это возможно) 

egor1855
Offline
Зарегистрирован: 24.10.2016

dmitron1036 пишет:

Зачем сделать такой(внешний) массив компонентом класса?

Чтобы не таскать этот массив сквозь все остальные классы. Экономия памяти, времени и т.д.

У меня десятка 2 датчиков и столько же управляемых устройств. Пишу "мозг"=модель, если по MVC. Он принимает решение на основе входных данных. Никаких включения/получения данных в нем быть не должно, кроме того, объекты этого класса будут работать параллельно, соответственно должны иметь всегда актульное состояние "пинов". Чтобы не передавать этот , в данном примере только массив (в дальнейшем тоже класс) , каждому объекту даю только ссылку на него. Получается массов един, о его обработчиков - много.

dmitron1036 пишет:

(замечу что это возможно) 

Мы в детстве так играли : Знаю, но не скажу ))))

Ничего невозможного нет , спосов миллион. Сейчас мне водится как вариант - просто передача указателя в класс (в данном примере на миссив) при инициализации класса. Соответственно работа с этим указателем (массивом в памяти) внутри класса будет отражаться в этом внешнем массиве без каких-либо дополнительных манипуляций.

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

Второй вариант - динамическое создание копии "внешнего" массива внутри каждой функции и после её отработки - актуализация "внешнего" массива. Здесь ничего переделывать в синтаксисе не нужно, но громоздко и "глупо", т.к. "в лоб".

Чувствую, должно быть элегантное и простое решение, пока поработаем )

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

egor1855 пишет:

У меня десятка 2 датчиков и столько же управляемых устройств. Пишу "мозг"=модель, если по MVC. Он принимает решение на основе входных данных. Никаких включения/получения данных в нем быть не должно, кроме того, объекты этого класса будут работать параллельно, соответственно должны иметь всегда актульное состояние "пинов". Чтобы не передавать этот , в данном примере только массив (в дальнейшем тоже класс) , каждому объекту даю только ссылку на него. Получается массов един, о его обработчиков - много.

ну, смотри, как у меня в велосипеде сделано #410: класс логики, класс-оболочка для класса логики, который строит массив из экземпляров класса логики, аппаратно опрашивает пины кнопок и впаривает результаты опроса нужному екземпляру класса логики.

egor1855
Offline
Зарегистрирован: 24.10.2016

Отлично, но мне нужен "сквозной" массив и всего-то, чего "велосипед-то изобретать, когда он уже есть ? )

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

egor1855 пишет:

Отлично, но мне нужен "сквозной" массив и всего-то

ты долбоёб?

egor1855
Offline
Зарегистрирован: 24.10.2016

КаллоуНций как всегда . Уйди, не говнякай собой тему.

egor1855
Offline
Зарегистрирован: 24.10.2016

В общем более рационального, чем передача указателя на "внешний" массив каждому объекту, кто может вляеть на этот массив я не придумал.

Применительно к первому посту это будет так :

byte *external_array;
external_array=(byte *)(&out_pins);//ссылка на первый элемент

У этого способа есть недостаток - нужно программно контролировать пределы массива.

Прогнал автозаменой с регуляркой исходники, вроде ничего не отвалилось )

Всем спасибо за участие, даже дурачкам, када ж без оных ))) !

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

Я так прикинул схему кода


/**/
//------------------------------------
// класс сенсор
class Cl_sens {
    const byte _pin; // пин
    byte * const _stat;//указатель на состояние датчика
  public:
    Cl_sens(byte pin, byte * stat): _pin(pin), _stat(stat) {}
    void setup() {
      pinMode(_pin, INPUT);
      *_stat = digitalRead(_pin);
    }
    void loop() {
      *_stat = digitalRead(_pin);
    }
};
//-----------------------------------
// класс мозг
class Cl_brain {
    byte * const _brain_array;//указатель на анализируемый массив
  public:
    Cl_brain(byte * brain_array): _brain_array(brain_array) {}
    void setup() {
      _brain_array[2] = _brain_array[0];
      _brain_array[3] = _brain_array[1];
    }
    void loop() {
      _brain_array[2] = _brain_array[0];
      _brain_array[3] = _brain_array[1];
    }
};
//----------------------------------------------------
// класс исполнительный механизм
class Cl_actuating_mechanism {
    const byte _pin; // пин
    byte * const _stat;//указатель на состояние механизма
  public:
    Cl_actuating_mechanism(byte pin, byte * stat): _pin(pin), _stat(stat) {}
    void setup() {
      pinMode(_pin, OUTPUT);
      digitalWrite(_pin, * _stat);
    }
    void loop() {
      digitalWrite(_pin, * _stat);
    }
};
//-------компоновка-------------------------
byte Array[4] = {0, 0, // -- данные сенсора
                 0, 0  // -- команды на исполнительные механизмы
                };
Cl_sens Sens1(/*пин*/2,/*ячейка памяти*/&Array[0]);
Cl_sens Sens2(/*пин*/3,/*ячейка памяти*/&Array[1]);
Cl_brain Brain(/*анализируемый массив*/Array);
Cl_actuating_mechanism Mech1(/*пин*/4,/*ячейка памяти*/&Array[2]);
Cl_actuating_mechanism Mech2(/*пин*/5,/*ячейка памяти*/&Array[3]);
//-------main()-----------------------------
void setup() {
  Sens1.setup();
  Sens2.setup();
  Brain.setup();
  Mech1.setup();
  Mech2.setup();
}

void loop() {
  Sens1.loop();
  Sens2.loop();
  Brain.loop();
  Mech1.loop();
  Mech2.loop();
}

ПС: Хотя правильнее заменить &Array[0] на Array; &Array[1]) на (Array+1)  ни и так далее.

egor1855
Offline
Зарегистрирован: 24.10.2016

Да, ну что Вы - сам датчик - отдельныя плата, общение с ним по Uart, их много. Вот типа этого https://www.gidroponika.su/gidroponika-svoimi-rukami.html/myopit/171-rastvornyj-uzel-dlya-gidroponiki.html

egor1855
Offline
Зарегистрирован: 24.10.2016

А тема исключительно для передачи "внешнего" массива "внутрь" каждого класса. Смысл такой: поступила команда "смыть унитаз". Мозг смотрит : включено наполнение унитаза, значит нет смысла его смывать, ставим в очередь, или "убиваем" эту команду, в зависимости от кучи сторонних обстоятельств.

Так же для датчиков: чтобы включить датчик - нужно подать порция раствора, смотрим -  бак сухой, и в очереди команда на мойку бака. Что же делать с командой замера ? Убить, ждать мойки, может она уже не актуальна будет ?

Ардуино для прототипирования, вообще это дело нейросети, принимать такие решения на основе многих неопределенностей, она в процессе, только это уже не атмега )

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

egor1855 пишет:

Да, ну что Вы - сам датчик - отдельныя плата, общение с ним по Uart, их много. 

 И что? Сенсор он и в UART сенсор. Если у вас UART гоняет пакеты хаотично, то сделайте UART диспечер. Класс сенсор  формирует запрос диспечеру UART сделать запрос на определенный удаленый датчик и данные засунуть в эту ячейку массива. И все.

egor1855
Offline
Зарегистрирован: 24.10.2016

qwone пишет:

ПС: Хотя правильнее заменить &Array[0] на Array; &Array[1]) на (Array+1)  ни и так далее.

Я так и делал в начале, только пом прикинул, как передать "аморфный" объект в качестве аргумента ?

Пока выход для СИ: пердача ссылки на указатель (до этой тему я не понимал как правильно их использовать), второй аргумент , а ещё лучше в самом начале данных по указателю - тип объекта.

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

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

Да последний мой скетч, он лучше выглядит так. Но массива там уже нет.

/**/
//------------------------------------
struct str_Array {
  bool sens1; // сенсор 1
  bool sens2; // сенсор 2
  bool mech1; // испол. механ 1
  bool mech2; // испол. механ 2
  str_Array(bool b1, bool b2, bool b3, bool b4 ): sens1(b1), sens2(b2), mech1(b3), mech2(b4) {}
};
//------------------------------------
// класс сенсор
class Cl_sens {
    const byte _pin; // пин
    bool  *_stat;//указатель на состояние датчика
  public:
    Cl_sens(byte pin, bool * stat): _pin(pin), _stat(stat) {}
    void setup() {
      pinMode(_pin, INPUT);
      *_stat = digitalRead(_pin);
    }
    void loop() {
      *_stat = digitalRead(_pin);
    }
};
//-----------------------------------
// класс мозг
class Cl_brain {
    struct str_Array  *Array;//указатель на анализируемый массив
  public:
    Cl_brain(struct str_Array *_Array): Array(_Array) {}
    void setup() {
      Array->mech1 = Array->sens1;
      Array->mech2 = Array->sens2;
    }
    void loop() {
      Array->mech1 = Array->sens1;
      Array->mech2 = Array->sens2;
    }
};
//----------------------------------------------------
// класс исполнительный механизм
class Cl_actuating_mechanism {
    const byte _pin; // пин
    bool * const _stat;//указатель на состояние механизма
  public:
    Cl_actuating_mechanism(byte pin, bool * stat): _pin(pin), _stat(stat) {}
    void setup() {
      pinMode(_pin, OUTPUT);
      digitalWrite(_pin, * _stat);
    }
    void loop() {
      digitalWrite(_pin, * _stat);
    }
};
//-------компоновка-------------------------
struct str_Array Array(0, 0, // -- данные сенсора
                       0, 0  // -- команды на исполнительные механизмы
                      );
Cl_sens Sens1(/*пин*/2,/*ячейка памяти*/&Array.sens1);
Cl_sens Sens2(/*пин*/3,/*ячейка памяти*/&Array.sens2);
Cl_brain Brain(/*анализируемый массив*/&Array);
Cl_actuating_mechanism Mech1(/*пин*/4,/*ячейка памяти*/&Array.mech1);
Cl_actuating_mechanism Mech2(/*пин*/5,/*ячейка памяти*/&Array.mech2);
//-------main()-----------------------------
void setup() {
  Sens1.setup();
  Sens2.setup();
  Brain.setup();
  Mech1.setup();
  Mech2.setup();
}

void loop() {
  Sens1.loop();
  Sens2.loop();
  Brain.loop();
  Mech1.loop();
  Mech2.loop();
}

 

egor1855
Offline
Зарегистрирован: 24.10.2016

А вот это :

bool * stat;

не логичнее делать как :

byte * stat;

Ведь boolean все равно в памати займёт байт (я не уверен, но где-то что -то мне так помнится). Кроме того исп. механизм может быть открыт не на 100%, это без каких-либо доработок позволяет использование byte - 0 выкл, 1-255 положение/сила.

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

egor1855 пишет:

А тема исключительно для передачи "внешнего" массива "внутрь" каждого класса.

массива унитазов?

egor1855
Offline
Зарегистрирован: 24.10.2016

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

egor1855 пишет:

А тема исключительно для передачи "внешнего" массива "внутрь" каждого класса.

массива унитазов?

Верно ! Вы чётко уловили суть задачи.

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

egor1855 пишет:

А вот это :

bool * stat;

не логичнее делать как :

byte * stat;

Вообще-то можно и так и так. Но структуре можно упаковать несколько битов в один байт. А bool использую, что бы те кто читали , поняли что у этой ячейки два состояния 1 и 0.

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

egor1855 пишет:

Верно ! Вы чётко уловили суть задачи.

так, в чём проблема?

egor1855
Offline
Зарегистрирован: 24.10.2016

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

так, в чём проблема?

У кого ?

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

egor1855 пишет:

У кого ?

ок. ТС ушёл в несознанку.

egor1855
Offline
Зарегистрирован: 24.10.2016

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

egor1855 пишет:

У кого ?

ок. ТС ушёл в несознанку.

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

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

egor1855 пишет:

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

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

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

egor1855 пишет:

dmitron1036 пишет:

Зачем сделать такой(внешний) массив компонентом класса?

Чтобы не таскать этот массив сквозь все остальные классы. Экономия памяти, времени и т.д.

У меня десятка 2 датчиков и столько же управляемых устройств. Пишу "мозг"=модель, если по MVC. Он принимает решение на основе входных данных. Никаких включения/получения данных в нем быть не должно, кроме того, объекты этого класса будут работать параллельно, соответственно должны иметь всегда актульное состояние "пинов". Чтобы не передавать этот , в данном примере только массив (в дальнейшем тоже класс) , каждому объекту даю только ссылку на него. Получается массов един, о его обработчиков - много.

dmitron1036 пишет:

(замечу что это возможно) 

Мы в детстве так играли : Знаю, но не скажу ))))

Ничего невозможного нет , спосов миллион. Сейчас мне водится как вариант - просто передача указателя в класс (в данном примере на миссив) при инициализации класса. Соответственно работа с этим указателем (массивом в памяти) внутри класса будет отражаться в этом внешнем массиве без каких-либо дополнительных манипуляций.

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

Второй вариант - динамическое создание копии "внешнего" массива внутри каждой функции и после её отработки - актуализация "внешнего" массива. Здесь ничего переделывать в синтаксисе не нужно, но громоздко и "глупо", т.к. "в лоб".

Чувствую, должно быть элегантное и простое решение, пока поработаем )

Короче я понял. 1)Вам надо изучать чистый С++ - тогда работать будет на порядок стабильней, без ардуиновских костылей.

2) Делай так: передавай в функцию не массив а указатель на массив.

3) Есть и другой метод. из области ООП.

 

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

dmitron1036 пишет:

без ардуиновских костылей.

Онкель, перелогинься, сука.

dmitron1036 пишет:

2) Делай так: передавай в функцию не массив а указатель на массив.

на массив унитазов.

dmitron1036 пишет:

3) Есть и другой метод. из области ООП.

нужно звать местнага пидагога.

egor1855
Offline
Зарегистрирован: 24.10.2016

dmitron1036 пишет:

Короче я понял. 1)Вам надо изучать чистый С++ - тогда работать будет на порядок стабильней, без ардуиновских костылей.

Согласен. Но, конкретно для данной задачи, конкретно в данный момент это нецелесообразно. Задача решена .

dmitron1036 пишет:

2) Делай так: передавай в функцию не массив а указатель на массив.

Согласен, так и реализовал, см. выше.

dmitron1036 пишет:

3) Есть и другой метод. из области ООП.

Их много )

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

Виртуальное ООП...

Есть виртуальная лампочка - у неё нет свойства "горячая", т.к. виртуальная лампочка не может быть горячей.

Но про неё можно это написать.

Где-то снаружи в заметках о виртуальной лампочке.