Здравствуйте, so5team, Вы писали:
Pzz>>Мы от чего защищаемся, от случайных ошибок, или от целенаправленного взлома?
S>От случайных. В сишном варианте у вас все манипуляции будут именно с var.v. И никто не защитит вас от того, что вы в var_distance.v по ошибке засунете var_weight.v.
В сишном варианте я напишу функции — аксессоры. А если мне не так уж важна та степень эффективности, которая достигается инлайновыми функциями, то я еще и внутренности этой структуры не вынесу в публичный заголовок.
Pzz>>А, ну да, у вас в команде нет индусов. Будут, это вопрос времени.
S>Нет проблем, можно привести историю и из своего опыта. Когда-то давно в большой (для проектной команды) кодовой базе величины таймаутов было решено задавать просто в миллисекундах и хранить это все просто в unsigned-ах. Соответственно, со временем полезли ошибки связанные с тем, что где-то из конфига величины считывались в секундах или минутах, а потом без должных преобразований или с неправильными преобразованиями это все уходило на вход функциям, где ожидались просто unsigned-ы.
А теста на читалку конфига не было?
Попрошу обратить внимание, что если для измерения длительностей по всему проекту изпользуется один и тот же тип (желательно typedef'нутый, конечно, а не просто unsigned int), то ерунда туда может пролезть только на границах системы — в той же читалке конфигов, например.
Классно, конечно, когда можно написать контракты, которые не позволяют вдуть часы туда, где ожидаются миллисекунды. Но такого пограничного кода не должно быть очень уж много, его и оттестировать можно.
Кстати, при чтении конфига мы все равно в каком-то месте читаем просто нетипизованный int, с этим ничего не поделаешь. В каком-то месте преобразование должно быть написано явно. Если этого места нет, или написано оно неправильно (например, путает минуты и секунды), то никакая система типов от этого все равно не спасет.
S>Такая же, как и вмешивание Go в разговор про преимущества C++ перед C (или наоборот).
Я ссылаюсь на Go ради примеров, как некоторые вещи можно сделать удачно, а не ради установления исторической справедливости. Полагаю, люди, придумавшие Go, знали C++ очень хорошо.
BFE>Инцидент произошел 12 апреля на рейсе Бангкок-Дэли. Как сообщает Times of India, когда лайнер набрал необходимую высоту, первый офицер Равиндра Нат ушел в туалет и прилег поспать в салоне бизнес-класса. Документы авиакомпании предписывают, чтобы минимум один пилот находился в кабине, контролируя полет и, в случае необходимости, отключая автопилот и принимая на себя управление. Однако командиру корабля Би Кею Сони также захотелось спать и он, включив автопилот, позвал двух бортпроводниц, в том числе молодую Канику Калу. Летчик объяснил им, как управлять самолетом, и ушел.
Здравствуйте, B0FEE664, Вы писали:
Pzz>>Кстати, аллокация на стеке тоже динамическая, стек тоже может кончиться. В отличии от кучи, при этом можно даже исключения не получить.
BFE>По правилам, рекурсивные вызовы разрешены только с подсчётом глубины вложенности и константным ограничением оной.
Сюрпрайз, это не гарантирует вообще ничего. Ты не ввёл запрета на то, что эта рекурсивность не будет вызвана где-то в глубокой вложенности, или в состоянии, когда на стеке кто-то не выделил временный большой блок данных.
Поэтому, кстати, я если и использую рекурсивность, то для заведомо мизерной возможной вложенности, иначе разворачиваю всё в цикл с очередью.
Здравствуйте, B0FEE664, Вы писали:
BFE>Если у вас есть подобъект, то его можно вызвать напрямую. Виртуальность нужна только если вы поднимаетесь от базового объекта к потомку — в другую сторону можно двигаться без виртуальности.
Потому что у меня есть, например, объект, в который можно писать. И есть, например, другой объект, который умеет писать в объект, в который можно писать. И мне сразу становится все равно, куда писать, в файл на диске, в сетевой сокет или в буфер в памяти.
Здравствуйте, B0FEE664, Вы писали:
M>>Выделенное есть. M>>Контейнеры и смарт указатели — да, их нет
BFE>Есть-то они есть, а какой в них смысл?
Контейнеры и смартпоинтеры тоже есть. А правило простое: если фича нужна — используй её. Если не нужна — не используй.
Вводить виртуальные функции без необходимости — не надо. А если надо — то лучше виртуальные функции, чем тот бред, что в С творят. И со всем остальным так же.
Здравствуйте, Pzz, Вы писали:
BFE>>Если у вас есть подобъект, то его можно вызвать напрямую. Виртуальность нужна только если вы поднимаетесь от базового объекта к потомку — в другую сторону можно двигаться без виртуальности.
Pzz>Потому что у меня есть, например, объект, в который можно писать. И есть, например, другой объект, который умеет писать в объект, в который можно писать. И мне сразу становится все равно, куда писать, в файл на диске, в сетевой сокет или в буфер в памяти.
Ну, к слову, такое можно вполне провернуть и на шаблонах без виртуальности. Правда, тогда всё, что пользуется интерфейсом writer'а переезжает в хидер, и код раздувается. На десктопе это не проблема, и компилеры обычно умеют избегать лишнего дублирования, но под MCU это не всегда так — например, armcc так не умеет, у него шаблонный код дублируется для каждого случая инстанциации, даже если двоичная реализация побитно совпадает с другими. Из-за этого использование шаблонов не всегда оправдано
Здравствуйте, so5team, Вы писали:
BFE>>Если у вас есть указатель на базовый объект, то этот указатель указывает только на часть объекта, а не на весь (целый) объект. Чтобы добраться до целого объекта можно использовать виртуальные методы, тогда (внутри метода) будет доступна та часть объекта, которая видна для типа, где этот виртуальный метод определён. S>Неверно. Виртуальный метод определяет поведение, а не то, к какой части объекта вы через него можете получить доступ.
Да неужели. А обычный метод поведение не определяет?
BFE>>Допустим у нас есть два типа C и B. Вы можете выделить общую часть и положить её в A, затем отнаследовать C и B от А, добавить виртуальные методы. Но как вы это будете использовать? S>Сдается мне, за рассказывание вам элементарных вещей нужно брать деньги.
Мне не надо рассказывать элементарные вещи. Расскажите лучше то, чего я не знаю.
S>Вот наглядный пример: S>
Кстати, #if / #else запрещены для исполняемого кода.
S>Сильно. Поскольку речь шла вообще не о знании C++. Но вы даже этого не смогли понять.
В чём я себе льщу?
S>Утверждали. И вам тут уже несколько человек указали на это.
Ладно. Виновен. Погорячился.
Здравствуйте, Pzz, Вы писали:
S>>От случайных. В сишном варианте у вас все манипуляции будут именно с var.v. И никто не защитит вас от того, что вы в var_distance.v по ошибке засунете var_weight.v.
Pzz>В сишном варианте я напишу функции — аксессоры. А если мне не так уж важна та степень эффективности, которая достигается инлайновыми функциями, то я еще и внутренности этой структуры не вынесу в публичный заголовок.
И после этого вы еще будете говорить про замусоревание, присущее шаблонам? Ахринеть.
Pzz>А теста на читалку конфига не было?
В конфиге и должно было быть значение в секундах (или минутах). А вот когда это значение использовалось чтобы взвести таймер, например, тогда оно и преобразовывалось в миллисекунды.
Pzz>Классно, конечно, когда можно написать контракты, которые не позволяют вдуть часы туда, где ожидаются миллисекунды. Но такого пограничного кода не должно быть очень уж много, его и оттестировать можно.
Вы, мягко говоря, утомили своим "оттестировать можно". Вам тут уже столько времени показывают как можно дешево (блин, реально дешево) сделать так, чтобы тестировать вообще не приходилось.
Но если все, чему вы научились за много лет -- это оттестировать в ручную, то тогда оставьте C++ таким неосиляторам, как я. И перестаньте рассказывать небылицы о том, в чем не разбираетесь.
S>>Такая же, как и вмешивание Go в разговор про преимущества C++ перед C (или наоборот).
Pzz>Я ссылаюсь на Go ради примеров, как некоторые вещи можно сделать удачно, а не ради установления исторической справедливости. Полагаю, люди, придумавшие Go, знали C++ очень хорошо.
А я пытаюсь вести разговор строго в рамках C++ против C без привлечения других примеров. Но т.к. вы про C++ не знаете, то все время вас тянет поговорить про Go.
Здравствуйте, Pzz, Вы писали:
S>>Чем они строгие? Любой в v может записать все, что захочет.
Pzz>Мы от чего защищаемся, от случайных ошибок, или от целенаправленного взлома?
Pzz>От целенаправленного взлома защититься нельзя. Какой-нибудь индус поправит твои контракты, и получит премию за то, что "починил код, который не компилировался". А ты потом на выходные останешься, чинить свой старый код, который не работает с новыми контрактами, потому что не был на них рассчитан.
Pzz>А, ну да, у вас в команде нет индусов. Будут, это вопрос времени.
Но с C++ претензия именно такая же, и тебя это не смущает
Здравствуйте, B0FEE664, Вы писали:
S>>Неверно. Виртуальный метод определяет поведение, а не то, к какой части объекта вы через него можете получить доступ. BFE> Да неужели.
Представьте себе.
BFE>А обычный метод поведение не определяет?
Обычный метод реализует конкретную операцию и вы знаете как именно он это делает. В случае виртуального метода вы не знаете как именно эта операция выполняется. Это и позволяет менять поведение в зависимости от типа наследника.
BFE>Мне не надо рассказывать элементарные вещи. Расскажите лучше то, чего я не знаю.
Так вы на элементарных вещах и плаваете.
BFE>Зачем здесь виртуальность? Она тут не нужна: BFE>
BFE>template< class launcher>
BFE>class launcher_commander {
BFE> launcher& launcher_;
BFE>
И тут БАХ! Внезапно "Си с классами" закончился. Кроме того, у вас не всегда будет возможность делать параметризацию шаблоном. Например, когда конкретные наследники и конкретные их пользователи разрабатываются разными командами и поставляются вам уже в виде готовых библиотек. Или когда конкретный объект выбирается прямо в run-time (но об этом вам, кажется, Marty уже говорил).
S>>Сильно. Поскольку речь шла вообще не о знании C++. Но вы даже этого не смогли понять. BFE>В чём я себе льщу?
M>Ни одна методология не заставит человек вспомнить всё и покрыть все возможные варианты тестами. Кроме самых простых случаев.
Поэтому существуют специальные организации занимающиеся проверкой работы программистов.
А вы думаете в таких областях как ядерная энергетика, космитечкая техника, гражданское авиастроение, железные дороги и т.п. сторонние организации работу програмистов не проверяют?
Всего пару дней спустя вся эта пыль в глаза... оказалась лишь пылью в глаза. Потому что великие и могучие сторонние организации, которые проверяют, чтобы программисты покрыли все варианты тестами... проверяют 100% покрытие кода тестами.
Здравствуйте, Nikе, Вы писали:
N>Ну-ну-ну, ты же тут уже писал как ты его знаешь. Это нормально для юниора, но не для сколько то опытного разработчика.
Здравствуйте, Nikе, Вы писали:
N>Сюрпрайз, это не гарантирует вообще ничего. Ты не ввёл запрета на то, что эта рекурсивность не будет вызвана где-то в глубокой вложенности, или в состоянии, когда на стеке кто-то не выделил временный большой блок данных.
Вы думаете это я правила составляю? Или вы думаете я будут перепечатывать все требования безопасности?
N>Поэтому, кстати, я если и использую рекурсивность, то для заведомо мизерной возможной вложенности, иначе разворачиваю всё в цикл с очередью.
Что такое "заведомо мизерная возможная вложенность"?
Здравствуйте, B0FEE664, Вы писали:
BFE>>>Часть функционала оказывается неиспользуемой. Зачем, например, виртуальные функции, если нет динамически создаваемых объектов? _>>Хы, и что в этом страшного то? Ты же ничем не платишь за их наличие в языке, если не используешь их в своём коде. BFE>Ничего страшного. Просто зачем? Как вы собираетесь использовать виртуальные функции?
Что зачем? Зачем эта функциональность в языке? Ну очевидно же, чтобы его могли использовать для очень разных задач, от МК до суперкомпьютеров. Для каждой задачи выбирается своё подмножество функциональности. Например для МК исключения, RTTI и т.п. обычно выключаются на уровне опций компилятора. И ничего страшного от этого не происходит.
_>>Более того, я могу предположить, что не существует вообще ни одной программы, которая использовала бы вот прямо все все возможности C++. BFE>Да я не об этом. Я о том, что требования к коду написаны так, что почти ничего из С++ использовать нельзя.
Что за требования то такие. Озвучь ка тут, чтобы можно было реально оценить. А то пока при обращение к конкретным примерам твои требования оказываются абсолютно ортогональны использованию C++.
Здравствуйте, B0FEE664, Вы писали:
BFE>Если у вас есть указатель на базовый класс, то вызов виртуального метода оправдан. BFE>Но откуда у вас указатель, если все объекты либо глобальные/статические, либо лежат на стеке? (разумеется рекурсивные вызовы без ограничения глубины на стеке запрещены)
Эммм, про оператор взятия адреса ты не в курсе? )))
И да, в коде на МК у меня виртуальных функций нет. Но это не потому, что мне как-то мешается отсутствие динамического выделения памяти, а исключительно потому, что они просто не были нужны.
Более того, у меня как раз не редко случается использование виртуальных функций без динамического выделения памяти на десктопе (хотя там с этим нет проблем). Как раз в виде передачи указателя на стековую переменную. И нужно это в одном весьма очевидном случае: когда одним из параметров библиотечной (т.е. чужой, которую мы не можем переписать под современный стиль с шаблонным параметром и использовать лямбду) функции является указатель на объект с виртуальным функциями (обычно порождённый от какого-то абстрактного класса из этой же библиотеки).
Здравствуйте, so5team, Вы писали:
S>>>Неверно. Виртуальный метод определяет поведение, а не то, к какой части объекта вы через него можете получить доступ. BFE>> Да неужели. S>Представьте себе.
Вообще-то принято считать, что виртуальный метод переопределяет поведение, а определяется поведение методом объекта.
BFE>>А обычный метод поведение не определяет? S>Обычный метод реализует конкретную операцию и вы знаете как именно он это делает. В случае виртуального метода вы не знаете как именно эта операция выполняется. Это и позволяет менять поведение в зависимости от типа наследника.
Вообще говоря, поведение метода можно изменить изменив состояние объекта.
BFE>>Мне не надо рассказывать элементарные вещи. Расскажите лучше то, чего я не знаю. S>Так вы на элементарных вещах и плаваете.
Где именно?
BFE>>Зачем здесь виртуальность? Она тут не нужна: BFE>>
BFE>>template< class launcher>
BFE>>class launcher_commander {
BFE>> launcher& launcher_;
BFE>>
S>И тут БАХ! Внезапно "Си с классами" закончился.
Это потому, что исходный код написан в парадигме С++. Тот же самый код можно переписать вообще без объектов, как вы понимаете. Я тут не стремился показать это, а только то, что виртуальность без динамической аллокации большого смысла не имеет.
S>>>Сильно. Поскольку речь шла вообще не о знании C++. Но вы даже этого не смогли понять. BFE>>В чём я себе льщу? S>В знании матчасти, которую вам следует подучить.
Здравствуйте, Marty, Вы писали:
M>>>Смотреть в отладке на регистры _>>Так регистры же все отображены в память, и соответственно банальный gdb без проблем подтягивает их значения (можно хоть в командной строке смотреть), и далее любая IDE показывает их в стандартном интерфейсе отладчика (отслеживания переменных). Что там ещё может быть нужно? ) M>Удобство пользования этим
Так я и спрашиваю, в чём проявляется это самое удобство.
Я уже молчу про то, что при использование библиотек от данного МК (типа HAL или LL), эти самые регистры не просто отображены в память, а ещё и находятся в соответствующих удобных объектных структурах, которые уж точно лучше подходят для контроля за периферией.