Стандарты программирования на С++. 101 правило и рекомендация - [84]
>static_cast
в окончательной версии (см. [Stroustrup00]):>template
> assert(dynamic_cast
> static_cast
> return static_cast
>}
>template
> typedef tr1::remove_reference
> assert(dynamic_cast
> static_cast
> return static_cast
>}
Эта пара функций (по одной для указателей и ссылок) просто проверяет согласованность двух вариантов преобразования. Вы можете либо самостоятельно приспособить >checked_cast
для своих нужд, либо использовать имеющийся в библиотеке.
[Dewhurst03] §29, §35, §41 • [Meyers97] §39 • [Stroustrup00] §13.6.2 • [Sutter00] §44
94. Избегайте преобразований, отменяющих >const
Преобразование типов, отменяющее >const
, может привести к неопределенному поведению, а кроме того, это свидетельство плохого стиля программирования даже в том случае, когда применение такого преобразования вполне законно.
Применение >const
— это дорога с односторонним движением, и, воспользовавшись этим спецификатором, вы не должны давать задний ход. Если вы отменяете >const
для объекта, который изначально был объявлен как константный, задний ход приводит вас на территорию неопределенного поведения. Например, компилятор может (и, бывает, так и поступает) поместить константные данные в память только для чтения (ROM) или в страницы памяти, защищенные от записи. Отказ от >const
у такого истинно константного объекта — преступный обман, зачастую караемый аварийным завершением программы из-за нарушения защиты памяти.
Даже если ваша программа не потерпит крах, отмена >const
представляет собой отмену обещанного и не делает того, чего от нее зачастую ожидают. Например, в приведенном фрагменте не происходит выделения массива переменной длины:
>void Foolish(unsigned int n) {
> const unsigned int size = 1;
> const_cast
> char buffer[size]; // Размер массива
> // ... // все равно равен 1
>}
В С++ имеется одно неявное преобразование >const_cast
из строкового литерала в >char*
:
>char* weird = "Trick or treat?";
Компилятор молча выполняет преобразование >const_cast
из >const char[16]
в >char*
. Это преобразование позволено для совместимости с API в стиле С, хотя и представляет собой дыру в системе типов С++. Строковые литералы могут размещаться в памяти только для чтения, и попытка изменения такой строки может вызвать нарушение защиты памяти.
Преобразование, отменяющее >const
, может оказаться необходимым для вызова функции API, некорректно указывающей константность (см. рекомендацию 15). Оно также полезно, когда функция, которая должна получать и возвращать ссылку одного и того же типа, имеет как константную, так и неконстантную перегрузки, причем одна из них вызывает другую:
>const Object& f(const Object&);
>Object& f(Object& obj {
> const Object& ref = obj;
> return const_cast
>} // возвращаемого типа
[Dewhurst03] §32, §40 • [Sutter00] §44
95. Не используйте преобразование типов в стиле С
Возраст не всегда означает мудрость. Старое преобразование типов в стиле С имеет различную (и часто опасную) семантику в зависимости от контекста, спрятанную за единым синтаксисом. Замена преобразования типов в стиле С преобразованиями С++ поможет защититься от неожиданных ошибок.
Одна из проблем, связанных с преобразованием типов в стиле С, заключается в том, что оно использует один и тот же синтаксис для выполнения несколько разных вещей, в зависимости от таких мелочей, как, например, какие именно заголовочные файлы включены при помощи директивы >#include
. Преобразования типов в стиле С++, сохраняя определенную опасность, присущую преобразованиям вообще, имеют четко документированное предназначение, их легко найти, дольше писать (что дает время дважды подумать при их использовании), и не позволяют незаметно выполнить опасное преобразование >reinterpret_cast
(см. рекомендацию 92).
Рассмотрим следующий код, в котором >Derived
— производный от базового класса >Base
:
>extern void Fun(Derived*);
>void Gun(Base* pb) {
>// Будем считать, что функция Gun знает, что pb в
>// действительности указывает на объект типа Derived и
>// хочет передать его функции Fun
>Derived* pd = (Derived*)pb; // Плохо: преобразование
>Fun(pd); // в стиле С
>}
Если функция Gun имеет доступ к определению >Derived
(например, при включении заголовочного файла >derived.h
), то компилятор имеет всю необходимую информацию о размещении объекта, чтобы выполнить все необходимые действия по корректировке указателя при преобразовании от >Base
к >Derived
. Но если автор >Gun
забыл включить соответствующий файл определения, и функции >Gun
видно только предварительное объявление класса >Derived
, то компилятор будет полагать, что >Base
и >Derived
— несвязанные типы, и интерпретирует биты указателя
Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.
Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.