All streams
Search
Write a publication
Pull to refresh
63
0
Дмитрий Пономарев @dm_frox

Программист

Send message
Интересно, когда все эти радости начнут поддерживать популярные компиляторы. Судя по поддержке С++11/14/17 как раз где-то к 2023 году. А до этого останется только обсуждать все это в блогах. И ведь еще дожить надо.
Спасибо! Интересная статья, давно собирался активно использовать анализаторы. А что вы можете сказать при анализатор, встроенный в Visual Studio?
Не совсем понял, о чем речь. Если можно, поподробнее.
Спасибо! Я с этим аспектом проблемы глубоко не разбирался, хотя призывал программировать без предупреждений почти в каждом раздела. Но замечу, что это флаги GCC, в других компиляторах по другому. И с таким количеством флагов работать не очень удобно. Считаю, что лучше, если программист распознает эти проблемы «в лицо», то есть видит в коде, а еще лучше, если сразу пишет правильный, более безопасный код.
Хочу еще раз обратить внимание, что никакой агитации за C# нет, просто хотелось показать, за счет чего, весьма близкий язык является более надежным и удобным. Сам я пишу на C++/C# где-то 50 на 50 уже много лет, и люблю оба языка. Считаю, что C++ программисту весьма полезно знать C# (ну на худой конец Java).
Нет. Это язык со статической типизацией, но она не строга ни в смысле гарантий, ни в смысле выразительности.

Статическая/динамическая типизация и строгая/нестрогая типизация это разные критерии классификации типизированных языков. Сильная типизация выделяется тем, что язык не позволяет смешивать в выражениях различные типы и не выполняет автоматические неявные преобразования. C++ спроектирован как язык со строгой типизацией, но с рядом послаблений в виде implicit conversions, из-за чего его чисто формально можно отнести к языкам с нестрогой типизацией. Вот статья на эту тему.
Так и не понял, что именно тут плохо. Какие-то общие слова, что можно делать ошибки. Так, наверное, можно вообще про любую языковую фичу написать в любом языке.

Программист может написать такие перегрузки, что потом будет пол дня думать, как они будут разрешатся в том или ином контексте. Я рекомендую так не делать. Потом перегруженные функции затрудняют анализ кода, особенно чужого, с помощью текстового поиска.
В C#, кстати, есть rvalue-ссылки и вообще move semantics?

Этого в C# нет.
То есть, если вы пишете управляющий ресурсом класс, то его, внезапно, надо сесть и писать. Нетривиальный вывод!

Не совсем понял, в чем суть возражения. Про классы, управляющие ресурсами у меня большая статья.
Неверная логика. Инициализация нулями не нарушает гарантий, даваемых С. Дело скорее в производительности.

Я как раз и имел в виду производительность.
Не понял логики. А как же порядок объявления членов?

В C# при создании объекта сначала инициализируются все поля объекта (значениями, заданными при объявлении или по умолчанию), затем вызывается конструктор базового класса или перегруженный конструктор, если они указаны в списке инициализации, затем сам конструктор.
Только это всё же не совсем то. Начиная с C++11 статик-переменные уровня функций инициализируются потокобезопасно, что, конечно, хорошо, но ведёт к очевидной дополнительной плате на синхронизацию при каждом входе в такую функцию.

За все надо платить. Но в данном случае немного, такой вызов обычно происходит один раз.
Не использовать сырое new. 2018 год на дворе уже, ё-моё.

Конечно, new/delete должны быть максимально инкапсулированы. Но полностью избавится от них не реально. C++ программист должен четко знать, как с ними правильно работать.
Использовать make_unique и make_shared.

Помогает, но не всегда. Эти шаблоны не позволяют использовать пользовательские удалители, и в этом случае придется работать с сырыми указателями и надо знать, как правильно писать выражения без потенциальных утечек памяти.
Судя по общему тону до этого, считается, что это в C# сделано типа хорошо?

Тут я выразился не совсем точно. Описываю ситуацию более подробно. Пусть в C# у нас есть базовый класс и производный. При создании экземпляра производного класса сначала инициализируются все поля базового класса и затем все поля производного. Только после этого вызывается конструктор базового класса и потом конструктор производного. Пусть в базовом классе определена виртуальная функция и она переопределяется в производном. Если в конструктор базового вставить вызов этой виртуальной функции, то вызовется переопределенная, соответственно, для объекта у которого уже инициализированы поля, но еще не вызывался конструктор. Довольно забавно. Если четко понимать, как это работает, то можно использовать.
В C# программист тоже может сделать в unsafe-блоке какую-нибудь ерунду, разве нет?

Программист пишет unsafe-блоки на свой страх и риск. Почти все гарантии .NET отменяются.
Да и говорить о сборщике мусора как о спасении от «значительной части» проблем, как будто единственный существующий ресурс — это память, ну очень примитивно.

Я же не говорил «всех проблем». Для оставшихся проблем есть интерфейс IDisposable. Конечно, работать с ним не так удобно, как с деструкторам в C++.
Согласен, что в C++ много еще более тонких моментов. Я описал базовые проблемы. Еще раз, никакой агитации за C# нет, хотелось показать, за счет чего весьма близкий язык является более надежным и удобным. Лично я считаю, что C++ программисту весьма полезно понимать как работают платформы .NET или Java. Большинство примеров не притянуто за уши, я натыкался на них в коде коллег (включая самого себя).
Ну корни у меня самые, что ни на есть плюсовые, с 90х. С++ я люблю и пишу на нем постоянно уже десятки лет. Моя цель — обратить внимание на проблемные моменты программирования на С++, которые легко могут привести к ошибкам. Программисты должны помнить об этих проблемах, не терять бдительности и при необходимости принимать необходимые меры. Никакой агитации за C# нет, просто хотелось показать, за счет чего, весьма близкий язык является более надежным и удобным. В целом стиль отзыва выглядит сумбурным, если не сказать истеричным. Практически ничего по существу ответить нельзя, так как никакой существенной критики нет, сплошные вопли.
Если программисту нужно совпадение строк, то правильным будет правое выражение, но по ошибке он может написать левое и получит результат с точностью до наоборот, условие будет верным, если строки не совпадают.
Ну может пример не совсем удачный. Но суть в том, что разработчики и пользователи интерфейса не всегда могут знать контекст реализации и константность может добавить дополнительные проблемы при реализации интерфейса, например вынудит использовать mutable. Вообще я планирую написать статью про константность в C++.
Иногда объявление интерфейса идет рука об руку с его реализацией, это делает одна команда. Тут проблем не может быть. Но, например, для plugin'а объявлять и использовать интерфейс может одна команда, а реализовывать интерфейс совершенно другая команда, у которой свой контекст при реализации интерфейса и он может не очень хорошо стыковаться с константностью. Например, доступ к свойству может быть реализован с использованием lazy evaluation.
Тут ничего не поделать, COM медленная (в смысле разработки) и печальная технология, C++17 уж точно не планировался для нее. Раньше COM объекты можно было писать на Visual Basic 6, Delphi. До сих пор можно писать на Qt. Это, конечно, побыстрее.
NVI это другая модель использования виртуальных, разновидность Шаблонного Метода Банды Четырех. Интерфейсные классы носят более технологический характер, с их помощью реализуется доступ к непрозрачному модулю. В C++ нет понятия интерфейс и его приходится моделировать с помощью виртуальных функций.
Ну, наверное, стоит уточнить: в русскоязычном мире, обсуждается перевод на русский язык. И как показывает опыт, словом «общепринятый» (тоже, кстати, пафосное слово) очень часто прикрываются личные вкусы и пристрастия автора.
Написать что-то принципиально новое на тему программирования довольно сложно. Моя цель была собрать и изложить все варианты, связанные с интерфейсными классами, так, что бы проектировщик мог сделать осознанный выбор. Моя практика показывает, что программисты очень редко правильно реализуют интерфейсные классы (хотя делают это достаточно часто), то есть для большинства данная статья содержит новый, ранее не знакомый материал и будет весьма полезна.
Для реализации COM на С++ существует специальная библиотека — ATL от Microsoft (входит в состав Visual Studio). По ней есть книги. Раньше у меня была отличная книга, где демонстрировалось создание COM объектов на C++ «руками», без всяких библиотек, но кто-то зачитал. Ну, вообще, COM уже не модная технология.
Ну на счет «дилетантский» я бы категорически возразил. Мейерса переводил и редактировал И.В.Красиков, авторитетнейший переводчик, он переводит и редактирует практически все книги по тематике C++ в издательстве «Вильямс» (Герб Саттер, Андрей Александреску, Николаи Джосаттис). Его переводы стали стандартом де-факто. В технической терминологии достаточно много тонкостей и не всегда первый попавшийся вариант перевода будет лучше.
Ну а теперь загляните в русский перевод этой книги. Там используется термин «интеллектуальный указатель». И в последнее время так переводят другие переводчики. На английском это всегда было smart pointer. При выборе перевода я, по возможности, стараюсь использовать широко известные публикации на русском.
Мне кажется, «умный» можно отнести к устаревшим терминам. В [Josuttis], [Meyers3] и ряде других последних книг, посвященных современному C++, используется термин «ителлектуальный».
Интерфейсы используются во многих языках программирования, и материалов по поводу того, зачем они нужны, тоже очень много. Но при их проектировании и реализации в С++ имеется много проблем, тонкостей, вариантов, связанных с особенностями языка С++. Разбору всего этого и посвящена статья.

Information

Rating
Does not participate
Location
Санкт-Петербург, Санкт-Петербург и область, Россия
Registered
Activity