реклама на сайте
подробности

 
 
13 страниц V  < 1 2 3 4 > »   
Reply to this topicStart new topic
> Как писать на С++ при создание приложений под ARM, Примеры
gladov
сообщение Jun 21 2011, 06:40
Сообщение #16


Частый гость
**

Группа: Свой
Сообщений: 169
Регистрация: 10-11-05
Из: Воронеж
Пользователь №: 10 687



Цитата(dxp @ Jun 20 2011, 11:32) *
Два, нет - три вопроса:
  1. Какое отношение имеет ООП к динамической памяти?
  2. Почему вы ставите знак равенства между С++ и ООП?
  3. Причём тут вообще паттерны проектирования? Какое они имеют отношение к ЯП С++?


Начну со второго: да, возможно я излишне строго приравнял C++ и ООП. Это конечно не так, я немного не то имел ввиду. Конечно, C++ дает нам много вкусностей помимо "классического" ООП. Но, согласитесь, основные достоинства языка С++ заключаются в его возможности писать ОО-код. Именно поэтому я не приравнял С++ и ООП, но поставил их совсем рядом и позволил себе в первом посте сместить акцент в сторону ООП.
Отношение ООП к динамике? Да никакого! Но во многих учебниках, а также в ВУЗах, преподается ООП (позвольте я все же буду тут писать про ООП, коль уж мой первый пост был де-факто про него) в тесной свзяке с динамической памятью, ибо так легче показать виртуализацию и полиморфизм. Поэтому и написал, что "ООП пытается тянуть за собой ....". Согласитесь, многие вещи удобнее реализовываются если использовать динамику? Однако этого лучше не делать, либо делать с умом, понимая механизмы и возможные последствия.
Паттерны? А разве плохо знать о них? А к С++ они имеют прямое отношение: их можно реализовать используя С++, а вот на С сделать то же самое гораздо сложнее.
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 21 2011, 08:09
Сообщение #17


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Да, стоит сделать new, как c++ тянет библиотечный malloc и еще иногда кучу всякого несовместимого. а если у вас защищенная ось, у каждого треда свой stack,data,heap, то и malloc должен быть свой(если есть, у меня нету heap пока,не нужно пока), и попробуй ему обясни куда надо класть данные. и еще многие вкусности c++ тянут...мотому я пишу C.
Хотя для графики(всяких там менюшек) лучше(удобнее) c++, мож буду юзать, когда нужно будет сложную графическую оболочку делать
а ООП и на C кодится, (какая разница, написать obj.func(x) или чтото типа class_func(&obj,x) ?), хоть и далеко ему до наворотов C++
Go to the top of the page
 
+Quote Post
dxp
сообщение Jun 21 2011, 08:47
Сообщение #18


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



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

Цитата(gladov @ Jun 21 2011, 13:40) *
Начну со второго: да, возможно я излишне строго приравнял C++ и ООП. Это конечно не так, я немного не то имел ввиду. Конечно, C++ дает нам много вкусностей помимо "классического" ООП. Но, согласитесь, основные достоинства языка С++ заключаются в его возможности писать ОО-код. Именно поэтому я не приравнял С++ и ООП, но поставил их совсем рядом и позволил себе в первом посте сместить акцент в сторону ООП.

Давайте наведём ясность с терминами, в частности с ООП. ООП - объектно-ориентированное программирование, в основе которого лежит описание программы в виде иерархий наследуемых объектов с виртуальными функциями (кои являются методами), с возможностью переопределять поведение методов на любом уровне иерархии. Т.е. если я просто определяю некий класс со своим представлением (данными) и интерфейсом (открытыми функциями-членами), объявляю объект[ы] этого класса и использую его[их] в программе - то это получается не ООП. Тут нет ни иерархий, ни наследования, ни методов (виртуальных функций). И даже если было бы и наследование, но без виртуальных функций, то и это было бы не ООП - т.к. ключевым свойством ООП является динамический полиморфизм - т.е. подмена поведения метода в наследнике на рантайме, а само по себе наследование этого не даёт.

Если вы посчитали, что уже использование классов - это ООП, то это ошибочное суждение. С++ - гибридный язык программирования. Он в явном виде поддерживает три парадигмы:
  1. Процедурую, когда программист разбивает код на функции (процедуры) и строит программу как совокупность вызовов процедур (точно как в традиционном С).
  2. Объектную, когда программист размещает код в компактных объектах, скрывая детали реализации с помощью инкапсуляции и абстракции и определяя интерфейс для взаимодействия объектов с внешним (для объекта) миром, а программу, строит определяя взаимодействия объектов между собой и с другими программными сущностями.
  3. Объектно-ориентированную, когда код строится в виде иерархий полиморфных классов (см выше).

Каждая парадигма имеет свои сильные и слабые стороны, и применять их все три надо к месту. С++ все эти три парадигмы поддерживает одинаково хорошо. И ни одна из них не порождает сколько-нибудь заметных накладных расходов в программе, чтобы их нельзя было использовать даже на 8-битных малышах, не говоря уже об АРМах. Где уместен С, там уместен и С++.

Цитата(gladov @ Jun 21 2011, 13:40) *
Отношение ООП к динамике? Да никакого! Но во многих учебниках, а также в ВУЗах, преподается ООП (позвольте я все же буду тут писать про ООП, коль уж мой первый пост был де-факто про него) в тесной свзяке с динамической памятью, ибо так легче показать виртуализацию и полиморфизм.

Совершенно нет. Никакого абсолютно отношения виртуальные функции и полиморфизм не имеют к работе со свободной памятью. Это полностью ортогональные вещи. Механизм виртуальных функций в С++ строится на таблицах указателей на функции - это вполне обычный механизм, хорошо известный ещё из языка С. Разница в том, что в С эти таблицы создавать, инициализировать адресами функций приходится вручную, в С++ этим занимается компилятор. Когда вы пишете код с таблицами указателей на функции на С, вам же не приходит в голову их размещать, в обязательном порядке вызывая malloc() - эти таблицы вполне нормально живут в статической памяти (да хоть в стеке, если время жизни таблицы достаточно для обслуживания кода, её использующего).

И если я описываю иерархию классов и создаю объекты статически, то и никакой динамической памяти и близко не возникает, а полиморфизм присутствует в полный рост. И ситуация тут наглядная и простая - уж во всяком случае попроще (не сложнее точно), чем в случае размещения объектов в свободной памяти

Цитата(gladov @ Jun 21 2011, 13:40) *
Поэтому и написал, что "ООП пытается тянуть за собой ....". Согласитесь, многие вещи удобнее реализовываются если использовать динамику?

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

В программах для РС, где присутствует GUI, это обычная практика - создавать объекты с помощью оператора new, т.к. GUI сам по себе динамичен - окна появляются и закрываются, действия пользователя на этапе написания программы не известны. Учитывая, что операция создания объекта в свободной памяти на РС не очень дорогая, этот подход широко применяется там и для других потребностей. Но и там злоупотреблять этим ни к чему. И недаром тов. Александреску даже разработал специальный быстрый менеджер памяти для использования его с небольшими объектами (он подробно описан в его книжке "Modern C++ design").

Цитата(gladov @ Jun 21 2011, 13:40) *
Паттерны? А разве плохо знать о них? А к С++ они имеют прямое отношение: их можно реализовать используя С++, а вот на С сделать то же самое гораздо сложнее.

Знать о них не плохо. Только это, вообще-то, приёмы проектирования, и реализовываться они могут на многих языках, а не только на С++. И уж нет никаких особы предпосылок к тому, чтобы считать их непригодными для реализации в embedded системах, в частности на ARM. Например, паттерн Singleton очень хорошо реализуется не то, что на ARM, но даже на AVR, и мы давно и широко его применяем.


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
scifi
сообщение Jun 21 2011, 09:21
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(dxp @ Jun 21 2011, 12:47) *
Если вы посчитали, что уже использование классов - это ООП, то это ошибочное суждение. С++ - гибридный язык программирования. Он в явном виде поддерживает три парадигмы:
  1. Процедурую, когда программист разбивает код на функции (процедуры) и строит программу как совокупность вызовов процедур (точно как в традиционном С).
  2. Объектную, когда программист размещает код в компактных объектах, скрывая детали реализации с помощью инкапсуляции и абстракции и определяя интерфейс для взаимодействия объектов с внешним (для объекта) миром, а программу, строит определяя взаимодействия объектов между собой и с другими программными сущностями.
  3. Объектно-ориентированную, когда код строится в виде иерархий полиморфных классов (см выше).

Спасибо за обзор. Лично для меня он оказался весьма полезным и своевременным.
Оказывается, я обычно реализую подход №2 ("объектный"), средствами языка Си: разделение интерфейса и реализации - module.h и module.c, сокрытие данных и служебных функций - ключевое слово static.
В связи с этим вопрос: не могли бы Вы привести примеры микроконтроллерных задач, в которых "объектно-ориентированный" подход даёт ощутимые преимущества?
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 21 2011, 09:33
Сообщение #20


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



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

Цитата
В связи с этим вопрос: не могли бы Вы привести примеры микроконтроллерных задач, в которых "объектно-ориентированный" подход даёт ощутимые преимущества?

пример - графический юзверь-интерфейс. я какраз щас задачку ставить буду, где сложный gui, все на том же cortex-m3, QT там не пойдет, прийдется писать свой, тут и применю с++, посему и залез в эти темку sm.gif
Go to the top of the page
 
+Quote Post
scifi
сообщение Jun 21 2011, 09:39
Сообщение #21


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(brag @ Jun 21 2011, 13:33) *
пример - графический юзверь-интерфейс. я какраз щас задачку ставить буду, где сложный gui, все на том же cortex-m3, QT там не пойдет, прийдется писать свой, тут и применю с++, посему и залез в эти темку sm.gif

При всём уважении, это голословное утверждение. Делал GUI (насколько сложный - тут мнения в любом случае разойдутся) именно "объектным" способом, никакой тяги к "полиморфизму" не ощутил.
Отсюда и вопрос. Хотелось бы с обоснованием, где именно полиморфизм реально помогает.
Go to the top of the page
 
+Quote Post
Axel
сообщение Jun 21 2011, 10:14
Сообщение #22


Местный
***

Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188



Цитата(scifi @ Jun 21 2011, 12:39) *
...где именно полиморфизм реально помогает.

Из практики: измерительная система, реализующая несколько различных измерений параметров одного объекта. Количество и последовательность измерений определяются пользователем. Оказалось удобным сделать классы конкретных измерений производными от общего базового виртуального класса. Структура программы получилась независимой от деталей (и изменений) каждой конкретной технологии.
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 21 2011, 10:30
Сообщение #23


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



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

тут не полиморфизм, тут иерархия классов, а это уже ооп, а не оп. хотя и полиморфизм хорошо подходит.
покрасить кнопочку в синий цвет и покрасить окошко в синий цвет - совершенно разные процедуры, хотя их можно обьеденить в один метод "покрасить виджет"
Go to the top of the page
 
+Quote Post
dxp
сообщение Jun 21 2011, 11:58
Сообщение #24


Adept
******

Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343



Цитата(scifi @ Jun 21 2011, 16:39) *
При всём уважении, это голословное утверждение. Делал GUI (насколько сложный - тут мнения в любом случае разойдутся) именно "объектным" способом, никакой тяги к "полиморфизму" не ощутил.
Отсюда и вопрос. Хотелось бы с обоснованием, где именно полиморфизм реально помогает.

Это вы зря - GUI, как раз, то место, где ООП рулит в полный рост. Не знаю, как у вас было организовано, но типовая схема такая: все объекты GUI являются членами иерархии классов, где в базовых классах объявляются методы (т.е. виртуальные функции), назначение которых выполнять действия, сходные по назначению, но разные по реализации. Например, у нас есть объекты: главное меню, выпадающее/всплывающее меню, пункт меню, графическая кнопка, строка состояния и т.п., а так же есть органы управления прибором - несколько кнопок или небольшая [плёночная] клавиатура. Нам нужно организовать управление всем ворохом графических объектов, но сделать это как-то единообразно. К примеру, нужно обрабатывать кнопку Right (перемещение вправо). Для этого мы в базовом классе иерархии объявляем виртуальную (если в самом базовом, то кошерно её объявлять чисто виртуальной - pure virtual) функцю void right(). И во всех производных классах, где это необходимо, эта функция переопределяется, чтобы получить для каждого класса своё поведение.

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

Так вот, код для реализации этого будет до безобразия прост:
Код
    TWidget *focus; // указатель на активный графический элемент (виджет)

   ...

    focus = ...;   //  focus присваивается адрес графического элемента - как правило это присваивание происходит
                      // внутри методов самих виджетов

   ...

    if( is_key_clicked(GUI::KEY_RIGHT)
    {
        focus->right();
    }

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

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

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

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

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


--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
Go to the top of the page
 
+Quote Post
Danis
сообщение Jun 21 2011, 13:27
Сообщение #25


Twilight Zone
***

Группа: Свой
Сообщений: 454
Регистрация: 17-02-09
Из: Челябинск
Пользователь №: 44 990



dxp, как у вас терпения хватает писать такие длинные посты? wink.gif Думаю, это будет отличным стимулом и введение в ООП, многих эмбедеров форума. Недаром говорят, «Новосибирск - город математиков и программистов»
Во общем респект и уважуха!!!

P.S. может в контексте этой темы и ваших постов Страуструпа выложить?


--------------------
Magic Friend
Go to the top of the page
 
+Quote Post
scifi
сообщение Jun 21 2011, 14:37
Сообщение #26


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(dxp @ Jun 21 2011, 15:58) *
В общем, в любом приложении, где есть общие по назначению, но разные по исполнению действия, уместно применять ООП - динамический полиморфизм отлично ложится на реализацию такой задачи.

Другими словами, средства полиморфизма из Си++ могут быть оправданы там, где на Си нужно было бы вводить "поле типа" или массив указателей на функции.
Неудивительно, что у меня нет к этому тяги: в моих задачах это редко встречается :-)
Ещё раз, спасибо за развёрнутое объяснение.
Go to the top of the page
 
+Quote Post
Danis
сообщение Jun 21 2011, 15:55
Сообщение #27


Twilight Zone
***

Группа: Свой
Сообщений: 454
Регистрация: 17-02-09
Из: Челябинск
Пользователь №: 44 990



Цитата(scifi @ Jun 21 2011, 17:37) *
Другими словами, средства полиморфизма из Си++ могут быть оправданы там, где на Си нужно было бы вводить "поле типа" или массив указателей на функции.


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


--------------------
Magic Friend
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 21 2011, 22:18
Сообщение #28


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



dxp, спасибо большое за обзорчик, вроде все и так понятно, но очень удобно, когда все собрано в кучке. распечатаю себе, как шпаргалку/краткое пособие wink.gif
Go to the top of the page
 
+Quote Post
haker_fox
сообщение Jun 22 2011, 01:05
Сообщение #29


Познающий...
******

Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125



dxp, спасибо за шикарные ответы!!! disco.gif
Не моголи бы Вы подсказать, по какой литературе обучались? Или это опыт?
Спасибо!


--------------------
Выбор.
Go to the top of the page
 
+Quote Post
andrewlekar
сообщение Jun 22 2011, 04:57
Сообщение #30


Знающий
****

Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163



Расказ про ООП конечно увлекательный, но стоит учитывать, что как только вы вылезете за область применения, описанную dxp (наследование от интерфейса и поточная обработка), то тут же вся система станет крайне неустойчивой. Конкретно: множественное наследование сразу ставит крест на проекте, перегрузка функций и операторов приводит к очень хитрым багам, развесистая иерархия наследования приводит к хрупкости системы - очень высокая связность элементов... Использование паттернов не имеет отношения к С++, но в микроконтроллерах не имеет особого смысла. Куда можно в AVR засунуть синглтон?! Использование шаблонов С++ сильно тормозит компиляцию и плохо контролируется по расходу памяти.
В общем, это неправда, что С++ оправдан везде, где оправдан С.
Go to the top of the page
 
+Quote Post

13 страниц V  < 1 2 3 4 > » 
Reply to this topicStart new topic
4 чел. читают эту тему (гостей: 4, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 21st July 2025 - 00:46
Рейтинг@Mail.ru


Страница сгенерированна за 0.01495 секунд с 7
ELECTRONIX ©2004-2016