Forger 20 8 мая Опубликовано 8 мая · Жалоба 3 hours ago, EdgeAligned said: Еще одна проблема, оставшаяся еще со времён Си - динамическое распределение памяти. По-моему аллокатор дин. памяти не относится к языку как таковому, что в плюсах, что в си используется вызов библиотечных malloc/free и реже других. Меня никогда не устраивал штатный аллокатор, поэтому тупо перегрузил штатные библиотечные функции дин памяти своими и уже там вызываю аллокатор. За основу взят TLSF как есть, но с немного другими настройками, особенно на контроллерах с мелким озу. Причем аллокатора пришлось делать два - один первичный, используется на "раскручивание" системы, совсем крохотный в 64 байта, а уже когда запустится все внутри подключается полноценный аллокатор. Связано с некоторыми библиотечными функциями, обойти по другому пока не получилось. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 158 9 мая Опубликовано 9 мая · Жалоба 21 час назад, tonyk_av сказал: А как же наследование? Как без него? Наследование в C++ прилеплено только лишь и потому, что язык преследует ООП-парадигму. Без наследования была бы не возможна концепция позднего связывания. И да - без наследования - легко. В Си не было никаких наследований и там не возникало вопросов "как без него". 21 час назад, EdgeAligned сказал: В частности, интерес представляют механизмы наследования, в том числе и виртуальные методы. Так же интересной плюшкой является перегрузка операторов. Для толстых проектов типа каких-то CAD-ов, геймдева и т.д. это вполне может пригодиться, соглашусь. 18 часов назад, Forger сказал: По-моему аллокатор дин. памяти не относится к языку как таковому, что в плюсах, что в си используется вызов библиотечных malloc/free и реже других. Не так. В плюсах ключевые слова new и delete зарезервированы как раз для управления динамическим выделением памяти. В Си вызывали malloc/free - а это функции. Самые обыкновенные. Так что да - в плюсах вполне однозначно изначально был заложен механизм работы с динамической памятью на уровне синтаксиса операций. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 20 9 мая Опубликовано 9 мая · Жалоба 45 minutes ago, Arlleex said: Не так. В плюсах ключевые слова new и delete зарезервированы как раз для управления динамическим выделением памяти. В Си вызывали malloc/free - а это функции. Самые обыкновенные. Вы не правы, эти самые new/delete как раз и вызывают библиотечные malloc/free и др. Если не верите, сделайте свои пустые заглушки на эти библиотечные функции и убедитесь лично под отладчиком. Я поэтому и переделал их, что при вызове new/delete используются по-умолчанию слишком простые и рисковые библиотечные malloc/free. Благо библитека позволяет чуть ли не все переписать под себя как угодно. В этом плане плюсы никуда не ушли от си 45 minutes ago, Arlleex said: Так что да - в плюсах вполне однозначно изначально был заложен механизм работы с динамической памятью на уровне синтаксиса операций. видимо мы говорим о несколько разных вещах ) я пришел к совершенно простому для меня объяснению - плюсы это по сути НАДСТРОЙКА на голым си, а никак не замена целиком. А вот с C# ситуация с дин памятью как раз в корне была изменена и уже такие мои "фокусы" вряд ли прокатят ( Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Arlleex 158 9 мая Опубликовано 9 мая · Жалоба 6 минут назад, Forger сказал: Вы не правы, эти самые new/delete как раз и вызывают библиотечные malloc/free и др. Если не верите, сделайте свои пустые заглушки на эти библиотечные функции и убедитесь лично под отладчиком. Я поэтому и переделал их, что при вызове new/delete используются по-умолчанию слишком простые и рисковые библиотечные malloc/free. Благо библитека позволяет чуть ли не все переписать под себя как угодно. В этом плане плюсы никуда не ушли от си Без разницы что они там вызывают. Факт есть факт - new, delete - такие же нативные операции среди ключевых слов языка, как и всякие там sizeof. Не нужно отрицать очевидное. Иначе в плюсах могли тупо оставить вызовы маллока функциями, как в си. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 20 9 мая Опубликовано 9 мая · Жалоба Just now, Arlleex said: Факт есть факт - new, delete - такие же нативные операции среди ключевых слов языка, как и всякие там sizeof. с этим спора нет, действительно мы не понял друг друга 1 minute ago, Arlleex said: Без разницы что они там вызывают. Это очень важно, если вы собрались активно пользовать дин память (особенно STL), то без полного контроля кучи очень велик риск потерять контроль над проектом А куча тут вшита в библиотеку, в нее не влезешь просто так, поэтому проще воткнуть другую, более прозрачную для отладки и контроля. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tonyk_av 37 9 мая Опубликовано 9 мая · Жалоба 43 minutes ago, Arlleex said: Наследование в C++ прилеплено только лишь и потому, что язык преследует ООП-парадигму. Без наследования была бы не возможна концепция позднего связывания. И да - без наследования - легко. Значит, не осознали его значимость и нужность по причине того, что пока не сформировалось объектное мышление. Простой пример: UART. Есть текстовый терминал, работающий по EIA-232, есть Модбас/RTU-мастер, работающий через EIA-485. Когда попробуете выделить у них общее, то с удивлением обнаружите, что у них на 95% общий код, и что создать для них общего предка становится естественным. Ну а разницу вынести в наследников. Так что тут я категорически не соглашусь, что наследование "в С++ прилеплено". Первое, что попалось на глаза: class FPU_device : protected IRQ { public: FPU_device( void ); ~FPU_device( void ); private: // Обработка исключений устройства с плавающнй точкой. virtual void IRQ_Handler( void ); }; То есть, следуя ОО-пардигме, любой объект, желающий обрабатывать прерывания, должен быть наследником класса IRQ и определить виртуальный метод IRQ_Handler(). class IRQ { .... protected: IRQ( void ); virtual ~IRQ( void ); //---------------------------------------------------------------------- // Обработчик прерывания. virtual void IRQ_Handler( void ) = 0; .... }; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 74 9 мая Опубликовано 9 мая · Жалоба В принципе, new/delete могут быть перегружены лдя классов. Касательно наследования - да нет, даже в довольно простых проектах, и совсем не в геймовых, можно беспроблемно применять наследование. Вот есть например какие-то свойства, общие для некоторой группы. И целесообразно создать базовый класс с описанием этих свойств, и от него написать наследуемые классы. При этом, если в каком-то наследуемом классе какой-то метод базового класса должен отличаться по реализации, можно записать этот метод как виртуальный в базовом и переопределить его в конкретном наследуемом классе. И еще особенность - наследование может быть не только публичным, но и приватным, то есть, работает тот же механизм разграничения видимости. Поэтому, наследование - весьма полезная фича, я бы сказал. То есть: class Base { public: void FooBase() { b = 0; } protected: int x; private: int b; }; class A: public Base { public: void FooA() { FooBase(); x = 0; // b = 40; // запрещено } }; class B: private A { public: void FooB() { FooA(); FooBase(); x = 10; } }; ..... A a; a.FooA(); a.FooBase(); // a.x = 5 // запрещено // a.b = 77; // запрещено B b; b.FooB(); // b.FooBase(); // запрещено // b.x = 4; // запрещено Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
tonyk_av 37 9 мая Опубликовано 9 мая · Жалоба 18 minutes ago, Arlleex said: Без разницы что они там вызывают. А вот и не без разницы! new-delete учитывают _тип_ объекта в отличие от банальных alloc-free. Более, того ещё и с учётом сигнатуры, что явно не доступно в С. EdgeAligned, мы с тобой одновременно об одном и том же, только чуть разными словами. 🙂 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 20 9 мая Опубликовано 9 мая · Жалоба 14 minutes ago, EdgeAligned said: В принципе, new/delete могут быть перегружены лдя классов. можно перегрузить даже "глобальный" new/delete, это заложено в базе языка, но это не всегда и порой совсем не удобно в моей ситуации пришлось "лезть глубже" с перегрузками под несколько другой причине, но вряд ли кому-то это будет интересно ) 15 minutes ago, tonyk_av said: определить виртуальный метод IRQ_Handler(). причем у вас о чисто виртуальный (= 0), что требует обязательной реализации этого метода в наследнике, то очень удобно, согласитесь )) довольно часто использую такой механим, очень полезный функционал, особенно для создания базовых интерфейсных классов (что типа паттерн "фасад"), через которые идет общение с наследниками второй полезный плюс такого класса - невозможно создать его экземпляр без наследования, Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 74 9 мая Опубликовано 9 мая · Жалоба и еще одна фича - объекты можно передавать по типу базового класса. Вкупе с чисто виртуальным базовым классом это дает интересную возможность. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 20 9 мая Опубликовано 9 мая · Жалоба 20 minutes ago, EdgeAligned said: и еще одна фича - объекты можно передавать по типу базового класса. Вкупе с чисто виртуальным базовым классом это дает интересную возможность. дык именно так поэтому такие зачастую чисто виртуальные классы и называют "классами-интерфейсами" ) например, базовый класс того же порта UART, а уже его реализация в т.ч. чисто программный UART - снаружи никому не видна вся библиотечная часть может быть закопана глубоко внутри и даже в таком виде заранее собрана в библиотеки, а снаружи все чинно-благородно ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 74 9 мая Опубликовано 9 мая · Жалоба А вот в этом как раз косяк языка. Понятие "интерфейс модуля" в нем нет совсем. Была некая попытка сделать его по-сишному через пару .cpp/.hpp и вынос реализаций методов вне класса в .cpp, но сделано было глючно - в случае с шаблонным классом эта затея уже не работает. Поэтому наследование от чисто виртуального базового класса для реализации интерфейса - в принципе это костыль. Еще один косяк языка, как следствие предыдущего - все инклюды и дефайны, написаные в .hpp, становятся видимыми везде при подключении файла. И хотя с дефайнами изобрели обходной костыль, но с инклюдами косяк так и остался. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 20 9 мая Опубликовано 9 мая · Жалоба 1 hour ago, EdgeAligned said: Еще один косяк языка, как следствие предыдущего - все инклюды и дефайны, написаные в .hpp, становятся видимыми везде при подключении файла в этом плане видимо шли путем унаследования всего что можно от голого си, в т.ч. не самые удачные решения, Впрочем, никто не заставляет добавлять в hpp файл все подряд )) в таких ситуациях добавляю только класс-интерфейс и самое нужное для создания его экземпляров/наследников, никаких посторонних дефайнов кстати, про дефайны - этот "атавизм" можно отчасти решить заменой на constexpr, где это возможно Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
EdgeAligned 74 10 мая Опубликовано 10 мая · Жалоба Я про то, что стоит только в каком-нить gpio.hpp подключить какой-нить "stm32f10x.h" и подключить этот gpio.hpp, так сразу stm32f10x.h становится видимым везде. Аналогично и с дефайнами, которые можно использовать для условной компиляции. И хорошо, что есть #undef, это хоть как-то спасает. Однако, действие constexpr аналогичным образом отменить нельзя. В общем, разграничение видимости этих моментов уже десятки лет остается недопиленным. Печалька. Я ж говорю - ядро языка не совершенствуется, "детские болячки" не исправлены, а тянутся годами, комитетчики на них забили и увлеклись нашлепыванием STL, которая тоже тянет всё те же косяки. А касательно топикстартера и его "пути воина" - блин, за 3 года и почти 60 страниц темы можно было уже выучить ++ от и до. Однако, у топикстартера какой-то бессистемный подход, пропускает базовые моменты, потому куча непоняток и нет большого прогресса. За всё время - только namespace, class/struct в самом базовом понятии и немного шаблонов. Стоило ли начинать? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Forger 20 10 мая Опубликовано 10 мая · Жалоба 2 hours ago, EdgeAligned said: Я про то, что стоит только в каком-нить gpio.hpp подключить какой-нить "stm32f10x.h" и подключить этот gpio.hpp, так сразу stm32f10x.h становится видимым везде. Я поступаю чуть иначе: этот stm32f10x.h подключаю внутри CPP, а внутри HPP оставляю только то, что необходимо для работы с ним. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться