one_eight_seven 6 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба Это не колхоз. Это C. Решение здесь - ABC (abstract virtual class), но я не знаю, какие у них накладные расходы, и применяются ли они при программировании микроконтроллеров. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба 29 minutes ago, Arlleex said: Может, это колхоз? Не колхоз. Делаю так для установки пользовательских обработчиков в прерывании драйверов, например. TRetVal TimDriver::setUserIrqHandler( const UserIrqHandlerNum &num, UserIrqHandler_t _handler ) { if (num == UserIrqHandlerNum::nLast) return rvSETTING_ERROR; m_ctrl.handler[static_cast<size_t>(num)] = _handler; return rvOK; } /// Указатель на функцию-обработчик прерывания, если драйвер позволяет использовать таковую. typedef bool ( *UserIrqHandler_t )(); Да и вообще, использую коллбеки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 154 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба О, ну тогда мое представление, вроде как, даже верное Спасибо! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 60 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба 1 minute ago, Arlleex said: О, ну тогда мое представление, вроде как, даже верное Возможно, что есть более красивые и Си++ - правильные способы. Но я действую так, как мне проще и понятнее. Пробовал тут с месяц назад разобраться с темой вызова нестатических методов класса по указателю. Исследовал тему делегатов и прочей подобной кухни. Прочитал пару статей. И пришёл к выводу, что указатели на нестатические методы в Си++, ИМХО, несколько уродливые. Куча ограничений. Иногда проще использовать Си-подобные методы решения задач. К слову, пытался сделать обработчик прерывания нестатическим методом класса, адрес на который подставляется в таблицу векторов, расположенную в ОЗУ. Просто экспериментировал... отчасти. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 6 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба Just now, Arlleex said: О, ну тогда мое представление, вроде как, даже верное Спасибо! Это невозможно сказать, без знания того, зачем вам c++. Если для ООП, то кардинально неверное. Если для более строгой типизации, и, может быть шаблонов - тогда может быть и верное. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 154 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба Я просто хочу быть трушным программистом на C/C++ (а как мне еще ответить на вопрос "зачем мне C++"?) Мне нравится "конструкторский" стиль построения программы, мне нравится весь синтаксический сахар плюсов. И все это в одном флаконе, да чтоб еще без накладных расходов (либо чтобы их наличие вызывало лишь смех). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 20 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба 27 minutes ago, haker_fox said: несколько уродливые. Куча ограничений. Мало статей читали ) Есть еще готовые решения на гитхабе (по поиску). Через делегаты все прекрасно и красиво работает, "уродливую часть" прячет в себе сам делегат, для чего оно в основном и нужен - упростить текст кода, спрятав от глаз лишние и опасные вещи (при работе с указателями). Вот чужой пример разных вариантов применения делегатов: Spoiler class DelegateSample { static int F(char value) { printf("Passed parameter: %c\n", value); return (char)value; } //F int instanceField; double A(unsigned long value, char c) { printf("Passed parameters: %lu, '%c; instance field: %d\n", value, c, instanceField); return 1.0 * instanceField / value; } //A double B(unsigned long value, char& c) const { printf("Passed parameters: %lu, '%c; instance field: %d\n", value, c, instanceField); return 1.0 * instanceField / value; } //B static double StaticMember(unsigned long value, char c) { printf("Passed parameters: %lu, %c\n", value, c); return 1.0 / value; } //B void Noret(int value) { printf("No return; passed parameter: %d\n", value); } //Noret public: DelegateSample(int aField) : instanceField(aField) {} double InstanceMember(unsigned long, char) { return 0.1; } static void Demo() { using namespace SA; printf("Single-cast delegates:\n\n"); DelegateSample sample(11); DelegateSample anotherSample(12); int touchPoint = 1; auto lambda = [&touchPoint](unsigned long a, char b) -> double { touchPoint++; printf("Delegate is assigned to lambda expression\n"); return a * 0.5; }; delegate<double(unsigned long, char)> dlambda; dlambda = lambda; // template instantiation deduced (inferred) double lambdaResult = dlambda(1, 'a'); printf("lambda result: %g, captured: %d\n", lambdaResult, touchPoint); auto d1 = delegate<double(unsigned long, char)>::create<DelegateSample, &DelegateSample::A>(&sample); auto dcompare = delegate<double(unsigned long, char)>::create<DelegateSample, &DelegateSample::A>(&sample); if (d1 == dcompare) printf("Two delegates are the same\n"); auto d2 = delegate<double(unsigned long, char)>::create<DelegateSample, &DelegateSample::A>(&anotherSample); auto d3 = delegate<double(unsigned long, char&)>::create<DelegateSample, &DelegateSample::B>(&sample); auto d4 = delegate<double(unsigned long, char&)>::create<DelegateSample, &DelegateSample::B>(&anotherSample); auto d5 = delegate<int(char)>::create<&DelegateSample::F>(); double ret1 = d1(1, 'a'); double ret2 = d2(2, 'b'); printf("Returned: %g, %g\n", ret1, ret2); char byRef = 'c'; double ret3 = d3(3, byRef); byRef = 'd'; double ret4 = d4(4, byRef); printf("Returned: %g, %g\n", ret3, ret4); d1 = d2; int ret5 = d5('e'); printf("Returned: %d\n", ret5); printf("Returned: %g, %g\n", ret3, ret4); printf("\nMulticast delegates:\n\n"); multicast_delegate<double(unsigned long, char)> md1, md2; if (!md2.isNull()) md2(111, '1'); ((md1 += d1) += d2) += d2; md2 += d2; md2 += d1; md2 += d1; md2 += d1; md2 += delegate<double(unsigned long, char)>::create<&DelegateSample::StaticMember>(); md2 += dlambda; // template instantiation deduced (inferred) if (!md1.isNull()) md1(5, 'F'); if (!md2.isNull()) md2(6, 'G'); printf("\nMulticast delegates, invocation with return:\n\n"); md2(14, 'm'); int closure = 0; md2(15, 'M', [=, &closure](size_t index, double* result) -> void { printf("\t\treturns: %g at %zd\n", *result, index); closure++; }); // ----- Multicast return handlers with capture: ------------------------------------------------ printf("Multicast return handlers with capture: ================\n"); double total = 0; double first = -1; double last = -1; md2(16, 'N', [&total](size_t index, double* result) -> void { printf("\t\treturns: %g at %zd\n", *result, index); total += *result; }); printf("Captured total: %g, average: %g \n", total, total/md2.size()); md2(16, 'N', [&total, &first, &last, &md2](size_t index, double* result) -> void { if (index == 0) first = *result; if (index == md2.size() - 1) last = *result; printf("\t\treturns: %g at %zd\n", *result, index); total += *result; }); printf("Captured total: %g, first: %g, last: %g \n", total, first, last); printf("not capturing, equivalent to md2(17, 'O'):\n"); } //Demo }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rkit 5 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба C++ это C, в котором любая задача делается чуть удобнее. Нет причин не использвать, кроме совместимости со старьем. И под старьем имеются в виду люди. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 126 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба 1 час назад, Arlleex сказал: А как надо тогда? Curiously recurring template pattern Немного дополнив пример из вики использую таким образом: template <class T> struct Base { void interface() { // ... impl()->implementation(); // ... } static void static_func() { // ... T::static_sub_func(); // ... } protected: T* impl() { return static_cast<T*>(this); } T* const impl() const { return static_cast<T const *>(this); } }; struct Derived : Base<Derived> { void implementation(); static void static_sub_func(); }; В классах-наследниках определяете свои реализации SetBaudRate(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rkit 5 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба 12 minutes ago, Forger said: Вот чужой пример разных вариантов применения делегатов: Весь этот фарш был упразднен еще стандартом 11го года. class MyClass { int f(int, bool); }; MyClass object; std::function<int(bool, int)> callback; callback = [&](bool b, int i) { return object.f(i, b); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
one_eight_seven 6 12 октября, 2021 Опубликовано 12 октября, 2021 (изменено) · Жалоба 18 minutes ago, rkit said: C++ это C... Только если вы C в последний раз видели году в 95. 42 minutes ago, Arlleex said: Я просто хочу быть трушным программистом на C/C++ Ну, это уже лет 20 - разные, пусть и сильно похожие, языки. В C++ настолько есть ВСЁ, что на нëм можно программировать сильно по-разному. Потому и спрашиваю - вам ООП или процедурный подход? Если процедурный, то можно коллбэки, если ООП, то не надо колбэками костылить. Изменено 12 октября, 2021 пользователем one_eight_seven Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 20 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба 16 minutes ago, rkit said: std::function Не во всех проектах допустимо применение std, раскройте его реализацию ради интереса, это как раз и есть делегат. Вот тут в комментах неплохо расписано про его "особенности". Минус std один - по делу и без дела увлекается дин. памятью (( Пример выше кстати соберется на C++11 и выше (из-за лямбд), не мой пример, но там показаны разные способы применения. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 154 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба 8 минут назад, one_eight_seven сказал: Потому и спрашиваю - вам ООП или процедурный подход? Ну не знаю я сейчас, насколько оптимален будет подход ООП. Обычно подход ООП подразумевает раздутие накладных на ровном месте. Я примерно представляю, какие накладные будут в callback-ах, и не представляю, какие будут при всех этих наследованиях от всяких абстракций и т.д. P.S. Сергей, спасибо за ссылку. Я внимательно изучу, как домой приду. Сходу тяжело "въехать" что там за конструкции такие страшные. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 20 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба 2 minutes ago, Arlleex said: какие будут при всех этих наследованиях от всяких абстракций и т.д. Они сокращают сложность и улучшают сопровождаемость кода из-за необходимости работы над предварительной проработкой структуры проекта, иначе этот ООП скорее навредит. Это как дай бензопилу тому, кто только ножовкой работал, так тот может себе конечности отрезать )) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 154 12 октября, 2021 Опубликовано 12 октября, 2021 · Жалоба 1 минуту назад, Forger сказал: Это как дай бензопилу тому, кто только ножовкой работал, так тот может себе конечности отрезать )) Я понимаю... Но тогда, если так рассуждать, то как "ножовочнику" научиться играть на бензопиле? А тем не менее, я еще ни одного проекта за свою практику не увидел от гуру плюсов (у нас на работе, например), чтобы хотя бы элементарный принцип "класс работы с протоколом написал - и таскаешь из проекта в проект" соблюдался - вечно допиливается, вечно адаптируется, и хрен бы с ним в одном месте - да нет же, в куче мест в исходниках. Но я пока еще верю, что всякие прикладные вещи можно написать так, чтобы таскать .cpp/.hpp-пару из проекта в проект, не модифицируя в них ничего. Это просто к слову. Еще ни в одной книжке по плюсам я не увидел плюсов и минусов того или иного способа забить гвоздь. Просто описание в стиле "ну можно вот так, а можно вот так - все это есть в C++". Круто, ага. Потом сел, открыл дизасм и волосы дыбом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться