Сергей Борщ 141 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба 11 часов назад, std сказал: В истории языка не было каких-либо "отмен". new(std::size_t, std::size_t) Цитата The placement form void* operator new(std::size_t, std::size_t) is not allowed because the matching signature of the deallocation function, void operator delete(void*, std::size_t), is a usual (not placement) deallocation function. (since C++14) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
dxp 65 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба 1 час назад, Arlleex сказал: Уже затертые до дыр примеры из учебников или ютуба про наследование собак и котов от абстрактного Animals ограничиваются только тем, что в цикле можно пройтись по массиву указателей на этот абстрактный Animals (при этом реальные указатели, соответственно, на объектах собак и котов) и вызвать у них метод Voice(). И все! Да я и в чистых Си могу так сделать - в структуре Animals поместить указатель на функцию Voice(), а структуры собак или котов будут или содеражть этот Animals в строго определенном месте, либо держать этот указатель на Voice() ровно в тех же смещениях, как и в структуре Animals. И ровно так же в массиве указателей то на собак, то на котов, но обобщенных указателем на Animals, гавкать и мяукать. И что же, это ООП-подход? А по-моему просто синтаксический сахар - как видно в Си это монструозно, а в плюсах нативно. В чистом С вам придётся в каждой структуре хранить указатель (vptr) на массив указателей (vtbl), создавать для каждого типа структуры этот массив, правильно инициализировать его. Адресом этого массива нужно проинициализровать vptr в каждой структуре, не перепутав где чей массив указателей. Вызов этот будет выглядеть как цепочка разыменовываний с вызовом в конце. И т.д. Тут немалое поле для ошибок. Вместо профита это будет выглядеть как микрофилиал ада. В С++ это ООП сводится к определениям и вызов - одна строчка. Одинаковая вне зависимости от конкретного типа и объекта. В этом суть полиморфизма - вид один и тот же, а поведение разное. И компилятор тут не ошибается, делает всю эту путанную рутину на раз. Кроме того, наследование даёт возможность нативно и прозрачно расширять функциональность. На С вам придётся либо переписывать руками код, либо включать в структуру структуру-"предка" в качестве члена, а это порождает для неё дополнительный уровень иерархии там, где он совсем не нужен. Ну, а так и С тогда "синтаксический сахар" для ассемблера. 🙂 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
haker_fox 61 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба 37 minutes ago, dxp said: Ну, а так и С тогда "синтаксический сахар" для ассемблера. 🙂 Не удержусь и продолжу ассоциативную цепочку: ассемблер - "синтаксический сахар" для машинных кодов. Или, что более верно, "сахарная пудра", т.к. полного засахаривания всё же не будет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tonyk_av 44 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба 48 minutes ago, Arlleex said: Вот пример: мне нужно принять строку по UART и выдать ее на дисплей, подключенный по SPI к тому же микроконтроллеру. 50 minutes ago, Arlleex said: А теперь: кто-то должен вызвать ReadString() и поместить считанную строку в Print() экрана. Кто? Вот есть у меня в ПЛК логгер. Он использует алгоритм Нэйгла, который берёт строки из буфера и отправляет их на печать. Строки складывают в буфер несколько задач. Ессно, возникает вопрос, кто будет запускать отправку? Очень просто: если очередной символ невозможно поместить в буфер, то запускается отправка содержимого буфера для его опорожнения. Или же отправка запускается по таймеру, потому что логгер наследует метод таймера, вызываемый по прерыванию. Так что _никаких_ функционального взаимодействий между объектами нет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба 6 минут назад, tonyk_av сказал: Или же отправка запускается по таймеру, потому что логгер наследует метод таймера, вызываемый по прерыванию. Так что _никаких_ функционального взаимодействий между объектами нет. Это уже костыль - таймеры и т.д. У меня тоже есть такой алгоритм. Я просто пишу в очередь write(), а внутри драйвера определяется, нужно ли в конце этого write() пнуть DMA, или он уже итак запущен и его пинать не нужно. DMA работает цепочечно - в прерывании по завершению транзакции смотрит в буфер - если там данные для отправки есть - вычисляет сколько их и заряжает отправку. И так по кругу. И это не означает, что никаких функциональных взаимодействий нет. Вы пишете, что никаких взаимодействий нет - но на самом деле толку от объекта, который живет сам по себе и никак не взаимодействует с внешним миром нет, и вы это итак подтвердили - этому вашему объекту надо каким-то образом "поместить символ в буфер". Значит некий кто-то пытается класть символ в буфер этого объекта - т.е. взаимодействие есть. То, что у объекта могут быть собственные механизмы внутри для поддержания некой функциональности - это совсем другое. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tonyk_av 44 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба 1 hour ago, Arlleex said: Это уже костыль - таймеры Это не костыль, а основа работы. Логгер может гнать данные не только в UART, но и в сетевой контроллер, оттуда и растут ноги алгоритма Нэйгла. 3 hours ago, Arlleex said: И это будет самый банальный функциональный стиль вызова методов Речь об этом, а не об отсутствии взаимодействия. Суть ООП как раз не в том, чтобы просто изолировать объекты, а в том, чтобы создать объекты, которые общаются друг с другом, не зная ничего о внутреннем устройстве друг друга. Тот же логгер не знает ничего о физическом интерфейсе, через который уходят данные, UART, USB или Ethernet. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба 24 минуты назад, tonyk_av сказал: Речь об этом, а не об отсутствии взаимодействия. Суть ООП как раз не в том, чтобы просто изолировать объекты, а в том, чтобы создать объекты, которые общаются друг с другом, не зная ничего о внутреннем устройстве друг друга. Тот же логгер не знает ничего о физическом интерфейсе, через который уходят данные, UART, USB или Ethernet. Так и нормальные Сишные программы изолируют реализации тех или иных физических интерфейсов, и некий send() может отправлять и в UART, и в USB, и в Ethernet. И в Си разные модули оформлены в виде отдельных единиц трансляции, чтобы не путаться (да как и в C++ тоже). Наружу торчит .h с неким API, который можно унифицировать для разных интерфейсов. И что, это ООП? Нет, это просто хорошо структурированная программа. Пока что все доводы, якобы применительные только к ООП-парадигме, звучат как некая надстройка над банальным функциональным кодированием, с определенными соглашениями о структуризации программы, которые еще и нативно хорошо поддержаны в соответствующих ООП ЯП. Нет никакой ООП-магии, я вижу все тот же код, все те же вызовы методов разных объектов, все те же банальные конструкции функциональных ЯП в C++ коде. Да, за счет парадигмы более строгой структуризации программы нам легче ее читать, в отличие от большинства Си программ, которые разработчики структурируют кто во что горазд. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 0 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба On 9/12/2023 at 2:08 PM, Arlleex said: Нет никакой ООП-магии мне вообще непонятно какой смысл менять шило С на мыло С++ если только за это не будут доплачивать - те же уязвимости из-за ручного управления памятью, если нужен технологически более высокий уровень - надо на Rust переходить как это делают сейчас в ядре Linux. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tonyk_av 44 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба 41 minutes ago, Arlleex said: Да, за счет парадигмы более строгой структуризации программы нам легче ее читать, Тут дело не только в лёгкости чтения. Понимаю, что пример не всем покажется убедительным, но другой пока на глаза не попался. Просто был проект, написанный на ни С и ХАЛ, который написал в ООП-стиле. Поскольку у меня были наработки, то я быстро реализовал проект на С++. В итоге размер кода уменьшился в 2 раза, но при этом к нему добавилась поддержка Модбас в опостасях RTU и TCP. Кстати, разница между RTU и TCP буквально в десятке строк, когда это делается, используя ООП. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба ...и начался холивар (священная война) - сишники против плюсоидов, линуксоиды против винтузятников, 8-битники против 32-битников, халоводы против регистровщиков 🙂 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sasamy 0 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба On 9/12/2023 at 2:57 PM, tonyk_av said: Просто был проект, написанный на ни С и ХАЛ, который написал в ООП-стиле. Поскольку у меня были наработки, то я быстро реализовал проект на С++. В итоге размер кода уменьшился в 2 раза У меня тоже есть пример - когда переписали проприетарный драйвер GPU Vivante для Linux размер кода уменьшился примерно в 10 раз, без плюсов. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 183 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба Мне, вопреки убеждениям, вдалбливаемым в универе, что три столпа ООП это инкапсуляция, полиморфизм и наследование, по своим ощущениям кажется, что самой главной характеристикой ООП является именно полиморфизм. Наследование и инкапсуляция к ООП весьма ортогональны, как приятный бонус, но не прямое следствие, порожденное постулатами ООП. Т.е. самое главное, что функциональщина пишется f(x), и мы четко знаем, что делает f() и допустим ли x для ее вызова. А в ООП мы делаем x.f(), и это, помимо большей логической связки объекта и метода, дает возможность не думать, какой конкретно f() мы должны вызвать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
std 8 12 сентября, 2023 Опубликовано 12 сентября, 2023 (изменено) · Жалоба 5 hours ago, Сергей Борщ said: new(std::size_t, std::size_t) (Я уже когда написал подумал "сейчас программисты накидают". Потому что крайне любят цепляться за соринку в глазу 🙂 неточности, оставляя порой самое важное за бортом). Да, спасибо. Я конечно же имел в виду не было отмены важных концепций. Я бы отметил auto_ptr, который удален в C++17. Но это не значит что удалили концепцию смартпоинтеров. Изменено 12 сентября, 2023 пользователем std Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
std 8 12 сентября, 2023 Опубликовано 12 сентября, 2023 (изменено) · Жалоба 7 hours ago, Arlleex said: Вы этим самым описываете весьма изолированное существование объектов. Объекты между собой должны взаимодействовать, как ни крути, иначе это бесполезные для мира программы объекты. Все верно. Объекты и классы должны быть максимально изолированы (это называется не иметь зависимостей, dependency-free). Каждый финальный рабочий объект должен представлять собой не имеющую зависимостей "изолированную" программу-объект полноценно выполняющую строго отведенные ей обязанности. Взял объект, может быть параметризовал, сконфигурировал впрыснул зависимости — и он завёлся, начал выполнять работу. Больше ничего и не надо. Это в идеале. К этому надо стремиться. См. принципы SOLID Потому давно замечено, что написанная таким образом программа приобретает целый ряд очень ценных свойств и качеств. Одно из них — само-замкнутость, целостность, устойчивость, отсутствие хрупкости, тестируемость. Насчет "Объекты между собой должны взаимодействовать, как ни крути" Если CUart (или его наследник) будет дергать методы CScreen - всё, конец. Класс-иерархия превращается в кашу взаимо-зависимостей. Потому что потом невозможно будет изъять из программы CUart и его периспользовать. CUart намертво будет переплетен с CScreen. А должно быть написано так, что в любой момент можно изъять CUart и использоавть его в другом проекте или в другой части проекта (а иногда - прямо в программе заменить его другим классом, этому способствует паттерн "Фабрика"). * - я не могу здесь распылиться на агрегирование, композицию и наследование, иначе пост превратится в стену текста. Зависимости при композиции не избежать в принципе и вообще всё в конечном итоге не так просто и баинарно, есть зависимости разного рода, дальние и ближние итд. Данный "общий" код будет "сверху", вынесен из CUart и из CScreen, содержась в некоем CDisplayManager, который в свою очередь содержит лишь экземпляры (или указатели) на CUart и CScreen. Это-то и будет тот, кто дергает выставленные методы объектов "из космоса" (о чем мы говорили выше). Однако, за все надо платить. И это тоже не бесплатно, это несет проблему. Проблемой здесь становится высокое "размытие" программы по классам и методам. Это анти-паттерн, который можно привнести в свои же собственные программы. Тогда вместо "цельности", "разумности" где каждый объект выполняет свое предназначение начнется иное - начнется ад из десятков классов с тонкой кодовой "кашицей" размытой между ними. Возникает "Yo-Yo problem", когда чтобы понять или редактировать программу приходится метаться между десятками файлов и вкладок или бегать вверх-вниз по файлу. Вдобавок, писать код подобным образом муторно. Лениво ваять дополнительные "клеевые" glue-объекты и классы (и интерфейсы). Всевозможные "CManager"-ы начинают возникать в неудержимом количестве. Но в конечном итоге платой будут определенные свойства программы. Надо соблюдать здравый смысл. Если у себя проект небольшой, ни к чему такой пуризм. Лучше повыкусывать потом код, чем обезуметь и самому же себе создать декомпозицию из 20 классов на 70. Изменено 12 сентября, 2023 пользователем std 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 86 12 сентября, 2023 Опубликовано 12 сентября, 2023 · Жалоба "Изолированы, должны быть изолированы максимально" 🙂 И это всё? Вся "парадигма"? Мдааа, не густо, не густо. Такую фиготеку и на процедурном Си принято мутить... Я думал, собравшиеся тут как-то более... более глубже понимают "цели и задачи" ООП, нежели как просто "изолировать всё и вся". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться