Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: C++ и ООП для микроконтроллеров AVR
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
Страницы: 1, 2
megajohn
Цитата(dxp @ May 11 2009, 19:22) *
... которая дает возможность использовать полиморфизм (в данном случае: переопределяемое на рантайме поведение).


...многие его средства - это абстракции уровня этапа компиляции.


а вот мне тут кажется противоречие. Или нет ?

и помнится, для реализации virtual нужно дополнительно место в RAM для каких-то таблиц ( давно где-то читал, но proof не дам - не знаю где читал )
Сергей Борщ
Цитата(doom13 @ May 19 2014, 12:08) *
Ваши предложения...
Код
class driver
{
public:
    void isr_handler();
    ....
};

driver Device1;

ISR(XXXX_vect)
{
    Device1.isr_handler();
};

msalov
Цитата(megajohn @ May 19 2014, 12:12) *
и помнится, для реализации virtual нужно дополнительно место в RAM для каких-то таблиц ( давно где-то читал, но proof не дам - не знаю где читал )


В "тело" каждого экземпляра класса добавляется указатель на таблицу виртуальных функций. Сами таблицы лежат в ПЗУ.
Сергей Борщ
Цитата(megajohn @ May 19 2014, 12:12) *
и помнится, для реализации virtual нужно дополнительно место в RAM для каких-то таблиц ( давно где-то читал, но proof не дам - не знаю где читал )
Таблица в количестве одной штуки на каждый класс с виртуальными функциями. Обычно хранится в памяти кода (avr-gcc до сих пор этого не умеет, хранит в ОЗУ). В каждом объекте такого класса один указатель (уже в ОЗУ) на эту таблицу. Таблица состоит из указателей на реализации виртуальных функций, т.е. если класс имеет одну виртуальную функцию, то таблица состоит из одного указателя. Примерно так, "на пальцах".
doom13
Цитата(Сергей Борщ @ May 19 2014, 12:19) *
Код
class driver
{
public:
    void isr_handler();
    ....
};

driver Device1;

ISR(XXXX_vect)
{
    Device1.isr_handler();
};

В таком исполнении ISR() нельзя сделать членом какого-то класса.
Сергей Борщ
Цитата(doom13 @ May 19 2014, 13:13) *
В таком исполнении ISR() нельзя сделать членом какого-то класса.
А зачем ему быть членом класса? Оно даже логически слабо в класс просится. Членом класса является isr_handler(). Допустим у вас 4 UARTa: класс - один, объектов - 4, вектора прерываний для каждого объекта свои и каждый вектор вызывает один и тот же обработчик но для своего, конкретного объекта. С натяжкой можно было бы согласиться спрятать ISR внутрь класса для периферии, которая на кристалле одна. Но где гарантия, что завтра не придется переносить этот код на кристалл, у которого этой периферии две или три?
doom13
Цитата(Сергей Борщ @ May 19 2014, 14:58) *
А зачем ему быть членом класса? Оно даже логически слабо в класс просится. Членом класса является isr_handler(). Допустим у вас 4 UARTa: класс - один, объектов - 4, вектора прерываний для каждого объекта свои и каждый вектор вызывает один и тот же обработчик но для своего, конкретного объекта. С натяжкой можно было бы согласиться спрятать ISR внутрь класса для периферии, которая на кристалле одна. Но где гарантия, что завтра не придется переносить этот код на кристалл, у которого этой периферии две или три?


Для каждого объекта, естественно, свой обработчик, его и задаём при помощи InitIsr (RegisterIsr если нравится).

Хорошо, но допустим есть какой-то класс Device, у него есть интерфейс управления (class Spi), интерфейс передачи данных (class Uart), системный счётчик (class Timer), для каждого необходимо задать обработчик прерывания. Ну а обработчик прерывания логически просится в класс Device, т.к. он непосредственно и выполняет операции необходимые для функционирования Device.

Допустим в системе пять таймеров, для каждого нужен свой обработчик. Логично всё "одинаковое" запихнуть внутрь класса, обработчик, который может отличаться для каждого таймера реализовать как callback-функцию.
Сергей Борщ
Цитата(doom13 @ May 19 2014, 15:46) *
Допустим в системе пять таймеров, для каждого нужен свой обработчик.
Угу. И каждый имеет свой вектор прерывания ISR(Timer_XX_vect) Как все пять обработчиков сделать статическими членами класса timer? Или я чего-то не понял в вашей идеологии?
Цитата(doom13 @ May 19 2014, 15:46) *
Логично всё "одинаковое" запихнуть внутрь класса, обработчик, который может отличаться для каждого таймера реализовать как callback-функцию.
Угу, как callback или как виртуальную функцию. Или построить наследников на шаблонах используя Curiously recurring template pattern (я так думаю, сам не пробовал пока).
doom13
Цитата(Сергей Борщ @ May 19 2014, 16:11) *
Угу. И каждый имеет свой вектор прерывания ISR(Timer_XX_vect) Как все пять обработчиков сделать статическими членами класса timer? Или я чего-то не понял в вашей идеологии?

Все пять обработчиков и не являются статическими членами класса Timer. У Timer есть только функция регистрации прерывания. Обработчик прерывания необходимо зарегистрировать после создания объекта.

Цитата(Сергей Борщ @ May 19 2014, 16:11) *
Угу, как callback или как виртуальную функцию. Или построить наследников на шаблонах используя Curiously recurring template pattern (я так думаю, сам не пробовал пока).

Тут не понял иронию, что не так в моей реализации? Всё работает и , по-идее, нет никаких противоречий. Можно и унаследовать если есть желание.
megajohn
Цитата(doom13 @ May 19 2014, 17:27) *
Все пять обработчиков и не являются статическими членами класса Timer. У Timer есть только функция регистрации прерывания. Обработчик прерывания необходимо зарегистрировать после создания объекта.


я так и делал, но нужно при регистрации передавать this и собсвенно иметь массив этих void* на this
Сергей Борщ
Цитата(doom13 @ May 19 2014, 16:27) *
Все пять обработчиков и не являются статическими членами класса Timer. У Timer есть только функция регистрации прерывания. Обработчик прерывания необходимо зарегистрировать после создания объекта.
Ну да. И в моем ISR() не является членом, но вам это почему-то не понравилось:
Цитата
В таком исполнении ISR() нельзя сделать членом какого-то класса


Цитата(doom13 @ May 19 2014, 16:27) *
Тут не понял иронию, что не так в моей реализации? Всё работает и , по-идее, нет никаких противоречий. Можно и унаследовать если есть желание.
Никакой иронии. У каждого свои детали реализации.
kolobok0
Цитата(yanvasiij @ May 19 2014, 10:33) *
Спасибо за методику... Основной недостаток - продолжительное время разработки. ..."на своей шкуре" испытать плюсы и минусы С++.
И плюс, про который все твердят - он помогает использовать старый код вновь гораздо легче, чем просто Си....


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

лучше всего как применять - описано у Гради Буча.
и идут по шагам.
1) анализ
2) дизайн
3) программирование

т.е. из вышесказанного можно сразу увидеть - если перескочить через 2 пункта и начать с третьего - то нифига это уже не ОО(а, д, п)... это будет уже
написание программы на си плас плас в стиле азм... что собственно встречается так часто, как наверное и упоминание о том, что ОО это фигня...

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

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

ОО это метода. и она вбирает в себя такие плюсы как статический код на всём протяжении разработки, удобство записи исходного кода, масштабируемость, гибкость и т.д..
A. Fig Lee
На маленьких задачах преимущества C++ не очевидны.
Нет особого смысла. Борьба с мельницами.
Ежели есть много объектов с похожими свойствами, но кое чем разным, то да, C++.
А если SPI, memory и mems датчик, то нет особого смысла.
Гдето так..
yanvasiij
megajohn doom13 andrewlekar Сергей Борщ msalov Спасибо! Очень полезные дебаты состоялись, есть о чем подумать.

Цитата(kolobok0 @ May 20 2014, 00:33) *
объектно ориентированый подход и есть методика. как применять - тут увы и ах кол-во специалистов очень мало. причина - не используют
(как правило) опыт ранее накопленный. или по другому - не понимают нафига вообще всё это...



Цитата(A. Fig Lee @ May 20 2014, 03:29) *
На маленьких задачах преимущества C++ не очевидны.
...


Я не спорю, что С++ для маленьких задач это, как использовать трактор для вскапывания земли в горшке с цветком. Просто у меня действительно начали вырисовываться большие задачи, поэтому я начал всерьез задумываться о подходе к программированию. Дело в том, что после десятка проектов и после значительного усложнения реашаемых задач пришел к выводу, что нужно хорошо подумать, хорошо по-проектировать прежде чем хвататься за клавиатуру. Нужно проработать концепцию, нужен этап еще до алгоритмов. Когда мыслишь процедурно, а не объектно, нет инструмента и нет какой то методики позволяющей разбить решаемую задачу на логические куски. Когда программисты пишут на Сях, каждый простите "др...ет как хочет". А когда люди пишут на ООП, они проектируют вполне конкретными методиками, тот же uml или idef. Я не говорю, что это лекарство в моем случае. Я просто хочу проверить поможет ли это мне на этапе проектирования. Конечно та задача, которую я озвучил выше мелковата для ООП, возникают вполне обоснованные вопросы типа "Нафига тут ООП?!". Но я бы замучался расписывать задачу скажем распознавания лиц с видеопотока, а уже если бы мне начали помогать ее разбивать на классы тут...
yanvasiij
-
juvf
смешали всё.

Ну во первых в avr-gcc от winavr нет операторов new и delete. Кто хочет с++ от winavr - должен это учесть.
Во 2-ых: C++ != ООП

я пишу всё исключительно на с++. где нужно - делаю классы, где нужно наследование, где нужно - динамику и контейнеры. А где не нужно - всё равно на с++, пусть даже и выглядит прога в стиле си. Зачем мне помнить на каком языке написана та или иная программа? Или тот или иной файл? Потом понадобится кусок кода из одного проекта использовать в другом - а они на разных языках. Пиши обёртки.... зачем это нужно?

И совет новичкам: хотите си - учите си. Хотите с++ - учите с++. (я бы советовал всёже с++). Не нужно писать на си, если нет ооп, и на с++ если есть ооп. Зачем учить 2 языка? Лучше углубитесь в изучение с++, при этом можно писать и без классов, и без стл, и без динамики, без ооп. По мере развития изучайте/добавляйте всякие няшки, которые отличают с++ от си. Даже без ооп с++ стоить юзать только за bool и ссылки, спэйсы..... Также в с++ удобно, что переменную можно объявить непосредственно перед использованием, в всяких форах.

Цитата
Я не спорю, что С++ для маленьких задач это, как использовать трактор для вскапывания земли в горшке с цветком.
Несогласен полностью. такой код/гаршок
Код
int main ()
{
printf("Hello world!")
for(;;);
return 0;
}
Где тут пахата трактором? компилируй компилятором с++, тот же хекс получится.
есть канечно "учителя" по с++ которые дают такие уроки.

Цитата
и сделаем из нее программу на C++:
Код
#include <iostream>  
#include <stdexcept>  
class App  
{
public:
    int Run()  
    {  
        std::cout << "Здраствуй Мир!!!\n";  
        throw std::runtime_error("Что-то плохое в нашей программе случилось.");  
        return 0;  
    }  
    ~App()  
    {  
        std::cout << "До свиданья.\n";  
    }  
};

int main(void)  
{
    try
    {
        App().Run();
    }
    catch(...)
    {
        throw;
    }
    return 0;
}

Чистой воды оверинженеринг (да ещё с ошибками). Такой перегруз можно и на си устроить и на асме.
andrewlekar
В C99 тоже можно переменную непосредственно перед использованием объявлять. Тоже есть bool. Ссылки полностью перекрываются указателями. Более-менее ценно в C++ - перегрузка функций и неймспейсы.
juvf
Цитата
Ссылки полностью перекрываются указателями
не перекрываются. указатель может указывать куда угодно, например на 0.

безопасный код.
Код
void f(MyType& i)
{
i = 100;
}

тоже безопасный код, но с указателем
Код
void f(MyType *i)
{
if(i != 0 )
   *i = 100;
}

Но и это не 100% безопасно.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.