Как создать класс матрицы?

Artem987

✩✩✩✩✩✩✩
2 Апр 2022
8
0
Подскажите, что исправить, чтобы матрицу вынести в собственный класс, для дальнейшего использования в светомузыке, но это позже, сейчас нужно создать класс матрицы. Заранее спасибо)
 

Вложения

poty

★★★★★★✩
19 Фев 2020
3,237
942
Для этого нужно описать нужные Вам свойства и методы класса. Определить, какие свойства и методы должны быть private, а какие - public. Иначе класс создавать бессмысленно.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,974
633
45
Да и если будет использоваться только один объект класса, то тоже не имеет смысла.
 
  • Лойс +1
Реакции: Boroda22

Boroda22

★✩✩✩✩✩✩
23 Фев 2022
251
42
Возможно проще создать структуру. Но если хочется ооп, то для одного объекта целесообразно применить паттерн синглтон.
 

Artem987

✩✩✩✩✩✩✩
2 Апр 2022
8
0
@poty, мне нужно просто при инициализации класса создать матрицу и внести её в переменную этого класса, чтобы в других функциях работать с матрицей через эту перемненную, все функции и переменные public
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
@Artem987, Вы куда-то не туда пошли. У Вас уже есть класс Max72xxPanel, в котором реализованы все функции матрицы. Инициализацию класса нужными значениями можно вынести в отдельную функцию (если Вам так удобно, потому что я в этом необходимости не вижу - достаточно структурной функции setup), либо в define, чтобы Вам глаза не мозолило .
Создание нового класса нужно если Вы что-то собираетесь переопределять в исходном классе или создавать новые уникальные методы/свойства. Пока в Вашем "классе" этого не наблюдается.
 

Artem987

✩✩✩✩✩✩✩
2 Апр 2022
8
0
@poty, мне нужно, чтобы я мог легко подключить столько матриц, сколько нужно и удобнее всего это класс, а ещё это изучение нового (само ООП я знаю, на основе Python, но нюансы Arduino и вызвали у меня этот вопрос), так же в классе будет как минимум функция в которую будет передаваться список значений частот музыки для цветомузыки
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
@Artem987, а создать столько экземпляров класса Max72xxPanel, сколько нужно, не судьба?
И нет большой разницы между классами в Python и C++, разве что уже когда что-то серьёзное начинаешь делать, влезать в нюансы реализации. Немного синтаксис различается, не более.
Класс должен реализовывать парадигму объекта, иначе это просто красивая обёртка обычных функций с добавленным кодом поддержки экземпляров. Если "функция в которую будет передаваться список значений частот музыки для цветомузыки" будет как-то связана с Max72xxPanel, заменяя, допустим, функцию отображения - да пожалуйста. Только в чём здесь вопрос-то? В синтаксисе?
 

Artem987

✩✩✩✩✩✩✩
2 Апр 2022
8
0
@poty, Да, вопрос скорее в синтаксисе
no matching function for call to 'Max72xxPanel::Max72xxPanel()'

1649142089859.png
 

bort707

★★★★★★✩
21 Сен 2020
3,066
914
@Artem987, ошибка на строчку выше подсвеченной строки, а именно в строке
Max72xxPanel matrix;
и на строчку ниже подсвеченной строки

Обе эти строчки создают один и тот же экземпляр обьекта Max72xxPanel, что уже само по себе глупость.
Разберитесь, что именно вы пытаетесь создать.
И не рано ли браться за написание своего класса... судя по коду, вы не имеете ни малейшего представления об обьектах и указателях...
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
Тут, скорее, проблема в том, что пустого конструктора в базовом классе нет.
 

bort707

★★★★★★✩
21 Сен 2020
3,066
914
@poty, да, сообщение об ошибке говорит именно об этом. Но это только синтаксическая ошибка, то есть мелочь... куда хуже что есть ошибки в логике. - в приведенном коде ДВА конструктора для одного экземпляра, что есть есть бред
 

bort707

★★★★★★✩
21 Сен 2020
3,066
914
@Boroda22, смотрите внимательней - в классе может быть описано два ( да хоть двадцать два) конструктора, но вызывается всегда один. А тут вызывается два, поэтому это ошибка.
 
  • Лойс +1
Реакции: Boroda22

Boroda22

★✩✩✩✩✩✩
23 Фев 2022
251
42
@bort707, ТС походу хотел инициализировать приватное поле с помощью конструктора, добавить геттеров и сеттеров, но видимо что-то пошло не так :)
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,974
633
45
Вероятно, нужно начинать с основ, на компе это все делать, там и отладка нормальная есть. А уже потом писать на ардуине.
 

SergejEU

★★✩✩✩✩✩
16 Сен 2020
120
73
@Artem987,
воспользуйтесь же технологией ООП!
1. Правильно наследуйте класс от родительского Max72xxPanel;
C++:
class Matrix : public Max72xxPanel
{
    ...
};
2. Используйте вложенные конструкторы класса;
3. Все методы и поля родительского класса Max72xxPanel акромя private будут вам доступны из коробки.
4. Добавляйте по необходимости свои методы или переопредляйте наследуемые.
 

Kir

★✩✩✩✩✩✩
28 Мар 2020
69
16
Избыточное цитирование. Отредактируй или сообщение будет удалено
@Artem987,
воспользуйтесь же технологией ООП!
1. Правильно наследуйте класс от родительского Max72xxPanel;
C++:
class Matrix : public Max72xxPanel
{
    ...
};
2. Используйте вложенные конструкторы класса;
3. Все методы и поля родительского класса Max72xxPanel акромя private будут вам доступны из коробки.
4. Добавляйте по необходимости свои методы или переопредляйте наследуемые.
Просто тупо наследоваться от какого-то класса бессмысленно, наследование это сильная связь с семантикой - "является". Которая в данном случае никак не соответствует действительности. К тому же потеряется вся соль ООП, и применение различных ООП техник будет затруднено. Кроме того, автор говорит, что ему нужно подключать не определенное количество матриц, и эти техники могут очень пригодиться для решения данной задачи. Композиция намного предпочтительнее в данном случае, что собственно автор и сделал.

@Artem987, no matching function for call to 'Max72xxPanel::Max72xxPanel()'
У вас вложенный экземпляр, который должен быть сконструирован до того как начнет работать код конструктора Matrix, это делается вот так:
C++:
class Matrix {
  public:
    Max72xxPanel matrix;
    Matrix(int pin, int width, int height)
     : matrix(pin, width, height) {
      
      matrix.setIntensity(5);
      for (byte i = 0; i < 4; i++) {
        // матрицы расположены криво, здесь поворачиваем
        matrix.setRotation(i, 1);
      }
      matrix.fillScreen(LOW);
      matrix.write();
      };
также обратите внимание, на сигнатуру конструктора Max72xxPanel, там принимаются не int, а byte.
 
  • Лойс +1
Реакции: Artem987

Boroda22

★✩✩✩✩✩✩
23 Фев 2022
251
42
Просто тупо наследоваться от какого-то класса бессмысленно, наследование это сильная связь с семантикой - "является".
И что? Наследование очень мощная штука в умелых руках. Если нам нужно расширить функционал какого-то класса, то наследование - это единственный верный вариант (еще лучше конечно использовать интерфейсы и DI, но у МК мне кажется не хватит памяти).
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
@Boroda22, так у товарища мания приравнивать ООП и полиморфизм. @Kir, из чего исходит такое мнение? Ничего из основного функционала родительского класса ТС изменять не будет. Вообще пока ничего внятного о причинах создания "своего класса" ТС не озвучил. Фактически, всё, что хочет ТС - создать обёртку, в которую засунуть свойства, которые не связаны с оригинальным объектом. В Ардуино уже есть такая обёртка: инициализатор setup и метод loop. Ничего другого я пока из его рассуждений не вижу к применению, даже мифических "техник ООП".
 

SergejEU

★★✩✩✩✩✩
16 Сен 2020
120
73
Композиция намного предпочтительнее в данном случае
И чем же предпочтительна? Потрудитесь впредь обосновывать ваши мысли более коррекно грамматически! Не нужно что-то додумывать за ТС, якобы не реализованное, - да вот если, да кабы, да во рту росли грибы.. Я исходил из того, что ТС нужно неограниченное количество экземпляров класса, но не неограниченное количество данных. Если же вы уверенны в обратном, что "нужно подключать не определенное количество матриц", то приведите хотя бы пример фабрики классов, где эта фича реализована.
 

Kir

★✩✩✩✩✩✩
28 Мар 2020
69
16
И что? Наследование очень мощная штука в умелых руках. Если нам нужно расширить функционал какого-то класса, то наследование - это единственный верный вариант (еще лучше конечно использовать интерфейсы и DI, но у МК мне кажется не хватит памяти).
Наследование далеко не единственный вариант.
Пример более очевидный, если вам нужно описать объект машина, вы же не станете при этом наследоваться от объекта типа двигатель, или станете?
Если унаследоваться от конкретной реализации, то потом уйти от неё будет нельзя, придется все таскать за собой, а если например, захочется подключить матрицу из адресных светодиодов, то придется все переделывать, что радости врят ли добавит.

Фактически, всё, что хочет ТС - создать обёртку, в которую засунуть свойства, которые не связаны с оригинальным объектом
Неожиданно, промелькнула здравая мысль, именно отсутствие прямой связи с объектом-исполнителем и развязывает руки в применении мифических ООП техник.

Кроме того, есть у меня подозрения, что автор хочет чтобы его код работал всегда с матрицей как с единым целым объектом, т.е. логика основной программы не должна беспокоится о том, сколько там фактически используется конкретных матриц, и как они вообще работают, если это так, то даже не композиция, а агрегирование будет более уместно, и оно же позволяет пойти дальше, и абстрагироваться от конкретной реализации, и если автор захочет сделать матрицу поярче и побольше, то подменить реализацию не составит большого труда, если будут предприняты соответствующие меры с применением мифических техник ООП, благодаря которым у каждого класса будет своя четкая задача, а не хаотичная каша из методов и сопутствующих их операторов if и switch в функции loop, а именно такой результат в подавляющем большинстве случаев и получается.

PS: О мифических техниках ООП рекомендую почитать этой книге.
 

poty

★★★★★★✩
19 Фев 2020
3,237
942
@Kir, что-то Вы плаваете в терминах. Наследование совершенно не исключает добавление методов объекта "обёртки". Если ТС захочет работать с другими матрицами, то использовать те же методы не получится, т.е., придётся переделывать "общие" методы в обёртке и проще будет написать специализированный класс. Никаких других высосанных Вами из пальца применений ТС не выказывал. Ему бы просто создать класс, а не заниматься прожектёрством, типа Вашего. А создавать в мизерной памяти МП монстра, управляющего сотней разнородных матриц - это оно, прожектёрство, и есть.
автор хочет чтобы его код работал всегда с матрицей как с единым целым объектом, т.е. логика основной программы не должна беспокоится о том, сколько там фактически используется конкретных матриц, и как они вообще работают
Почитайте, что хочет ТС:
в классе будет как минимум функция в которую будет передаваться список значений частот музыки для цветомузыки
Похоже это на тот бред, что Вы написали?
если автор захочет сделать матрицу поярче и побольше, то подменить реализацию не составит большого труда
в любом случае, даже с использованием базового класса без изменений. Если базовый класс таких методов не предоставляет, то какие бы мифические практики не применялись, результата не будет.
 

Boroda22

★✩✩✩✩✩✩
23 Фев 2022
251
42
Если унаследоваться от конкретной реализации, то потом уйти от неё будет нельзя, придется все таскать за собой, а если например, захочется подключить матрицу из адресных светодиодов, то придется все переделывать, что радости врят ли добавит.
запросто, будь это интерфейсы🙂. я полагаю мы сильно отклонились от темы, и скатываемся в вечные холивары. ТС-у есть что почерпнуть из этой темы.

И чем же предпочтительна?
композиция предпочтительна тем, что не нужно беспокоиться об объекте, он сам изменит свое состояние

Пример более очевидный, если вам нужно описать объект машина, вы же не станете при этом наследоваться от объекта типа двигатель, или станете?
пример конечно стремный, хотя бы привели пример с квадратом и прямоугольником. смотря что вы имеете ввиду под термином "машина". если это автомобиль, то это одно, а если это часть чего-то... так что контекст рулит🙂
 

Kir

★✩✩✩✩✩✩
28 Мар 2020
69
16
запросто, будь это интерфейсы🙂. я полагаю мы сильно отклонились от темы, и скатываемся в вечные холивары. ТС-у есть что почерпнуть из этой темы.
Да, но мы же не с интерфейсом имеет дело, а с конкретной реализацией и предлагают наследоваться именно от реализации.

пример конечно стремный, хотя бы привели пример с квадратом и прямоугольником. смотря что вы имеете ввиду под термином "машина". если это автомобиль, то это одно, а если это часть чего-то... так что контекст рулит🙂
Пример отличный, явно показывает всю абсурдность попытки создать обобщённую сущность, используя наследование от конкретной реализации.


И чем же предпочтительна?
Тем, что композиция образует более слабую связь, нежели наследование, а значит более гибкую.
В том контексте, котором собиралось использоваться предложенное наследование, композиция позволяет достичь ровно того же результата (просто тягать за методы другой объект).
Если пойти чуть дальше, и композицию заменить агрегированием абстрактного интерфейса, то получаем возможность менять конкретные реализации, которые могут быть совершенно не похожи друг на друга с точки зрения интерфейса , при этом совершенно не вмешиваясь в код написанного уже компонента. Кроме того наследование никак не по способствует облегчению масштабирования по количеству подключаемых матриц, а композиция, не говоря уже про агрегацию абстрактных интерфейсов, могут очень даже органично вписаться в решение данной задачи, инкапсулируя в себе всю логику, а наружу отдавая простой интерфейс для использования. В перспективе получаем легко переиспользуемый класс, который можно использовать в других проектах как есть. А предложенное выше наследование, таких перспектив не дает.