» » » Герб Саттер - Стандарты программирования на С++. 101 правило и рекомендация


Авторские права

Герб Саттер - Стандарты программирования на С++. 101 правило и рекомендация

Здесь можно скачать бесплатно "Герб Саттер - Стандарты программирования на С++. 101 правило и рекомендация" в формате fb2, epub, txt, doc, pdf. Жанр: Программирование, издательство Издательский дом "Вильямс", год 2005. Так же Вы можете читать книгу онлайн без регистрации и SMS на сайте LibFox.Ru (ЛибФокс) или прочесть описание и ознакомиться с отзывами.
Герб Саттер - Стандарты программирования на С++. 101 правило и рекомендация
Рейтинг:
Название:
Стандарты программирования на С++. 101 правило и рекомендация
Автор:
Издательство:
Издательский дом "Вильямс"
Год:
2005
ISBN:
5-8459-0859-0
Скачать:

99Пожалуйста дождитесь своей очереди, идёт подготовка вашей ссылки для скачивания...

Скачивание начинается... Если скачивание не началось автоматически, пожалуйста нажмите на эту ссылку.

Вы автор?
Жалоба
Все книги на сайте размещаются его пользователями. Приносим свои глубочайшие извинения, если Ваша книга была опубликована без Вашего на то согласия.
Напишите нам, и мы в срочном порядке примем меры.

Как получить книгу?
Оплатили, но не знаете что делать дальше? Инструкция.

Описание книги "Стандарты программирования на С++. 101 правило и рекомендация"

Описание и краткое содержание "Стандарты программирования на С++. 101 правило и рекомендация" читать бесплатно онлайн.



Эта книга поможет новичку стать профессионалом, так как в ней представлен сконцентрированный лучший опыт программистов на С++, обобщенный двумя экспертами мирового класса.

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

Опытные программисты найдут в ней советы и новые рекомендации, которые можно сразу же принять на вооружение. Программисты-профессионалы могут использовать эту книгу как основу для разработки собственных стандартов кодирования, как для себя лично, так и для группы, которой они руководят.

Конечно, книга рассчитана в первую очередь на профессиональных программистов с глубокими знаниями языка, однако она будет полезна любому, кто захочет углубить свои знания в данной области.






Преобразование, отменяющее const, может оказаться необходимым для вызова функции API, некорректно указывающей константность (см. рекомендацию 15). Оно также полезно, когда функция, которая должна получать и возвращать ссылку одного и того же типа, имеет как константную, так и неконстантную перегрузки, причем одна из них вызывает другую:

const Object& f(const Object&);


Object& f(Object& obj {

 const Object& ref = obj;

 return const_cast<Object&>(f(ref)); // преобразование

}                                    // возвращаемого типа

Ссылки

[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 — несвязанные типы, и интерпретирует биты указателя Base* как биты указателя Derived*, не делая никаких коррекций, которые могут диктоваться размещением объекта в памяти!

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

extern void Fun(Derived*);


void Gun(Base* pb) {

 // Если мы гарантированно знаем, что pb на самом деле

 // указывает на объект типа Derived:


 // Преобразование в стиле С++

 Derived* pd = static_cast<Derived*>(pb);


 // В противном случае следует использовать

 // = dynamic_cast<Derived*>(pb);

 Fun(pd);

}

Теперь, если у компилятора недостаточно статической информации об отношениях между Base и Derived, он выведет сообщение об ошибке, вместо того чтобы автоматически применить побитовое (и потенциально опасное) преобразование reinterpret_cast (см. рекомендацию 92).

Преобразования в стиле С++ могут защитить корректность вашего кода в процессе эволюции системы. Пусть, например, у вас есть иерархия с корнем в Employee, и вам надо определить уникальный идентификатор ID для каждого объекта Employee. Вы можете определить ID как указатель на сам объект Employee. Указатели однозначно идентифицируют объекты, на которые указывают, и могут сравниваться на равенство друг другу — что в точности то, что нам и надо. Итак, запишем:

typedef Employee* EmployeeID;


Employee& Fetch(EmployeeID id) {

 return *id;

}

Пусть вы кодируете часть системы с данным дизайном. Пусть позже вам требуется сохранять ваши записи в реляционной базе данных. Понятно, что сохранение указателей — не то, что вам требуется. В результате вы изменяете дизайн так, чтобы каждый объект имел уникальный целочисленный идентификатор. Тогда целочисленный идентификатор может храниться в базе данных, а хэш-таблица отображает идентификаторы на объекты Employee. Теперь typedef выглядит следующим образом:

typedef int EmployeeID;


Employee& Fetch( EmployeeID id ) {

 return employeeTable_.lookup(id);

}

Это корректный дизайн, и вы ожидаете, что любое неверное употребление EmployeeID должно привести к ошибке времени компиляции. Так и получается, за исключением следующего небольшого фрагмента:

void TooCoolToUseNewCasts(EmployeeID id) {

 Secretary* pSecretary = (Secretary*)id; // Плохо:

 // ...                                  // преобразование в стиле С

}

При использовании старой инструкции typedef преобразование в стиле С выполняет static_cast, при новой будет выполнено reinterpret_cast с некоторым целым числом, что даст нам неопределенное поведение программы (см. рекомендацию 92).

Преобразования в стиле С++ проще искать в исходных текстах при помощи автоматического инструментария наподобие grep (но никакое регулярное выражение grep не позволит выловить синтаксис преобразования типов в стиле С). Поскольку преобразования очень опасны (в особенности static_cast для указателей и reinterpret_cast; см. рекомендацию 92), использование автоматизированного инструментария для их отслеживания — неплохая идея.

Ссылки

[Dewhurst03] §40 • [Meyers96] §2 • [Stroustrup00] §15.4.5 • [Sutter00] §44

96. Не применяйте memcpy или memcmp к не-POD типам

Резюме

Не работайте рентгеновским аппаратом (см. рекомендацию 91). Не используйте memcpy и memcmp для копирования или сравнения чего-либо структурированного более, чем обычная память.

Обсуждение

Функции memcpy и memcmp нарушают систему типов. Использовать memcpy для копирования объектов — это то же, что использовать ксерокс для копирования денег, а сравнивать объекты при помощи memcmp — то же, что сравнивать двух леопардов по количеству пятен. Инструменты и методы могут казаться подходящими для выполнения работы, но они слишком грубы для того, чтобы сделать ее правильно.

Объекты С++ предназначены для сокрытия данных (возможно, наиболее важный принцип в разработке программного обеспечения; см. рекомендацию 11). Объекты скрывают данные (см. рекомендацию 41) и предоставляют точные абстракции для копирования этих данных посредством конструкторов и операторов присваивания (см. рекомендации с 52 по 55). Пройтись по ним грубым инструментом типа memcpy — серьезное нарушение принципа сокрытия информации, которое зачастую приводит к утечкам памяти и ресурсов (в лучшем случае), аварийному завершению программы (в случае похуже) или неопределенному поведению (в самом худшем случае). Например:

{

 // Создаем два int в памяти

 shared_ptr<int> p1(new int), p2(new int);


 memcpy(&p1, &p2, sizeof(p1)); // Так делать нельзя!!!

} // Утечка памяти: p2 никогда не удаляется

  // повреждение памяти: p1 удаляется дважды

Неверное применение memcpy может влиять на такие фундаментальные свойства, как тип и сущность объекта. Компиляторы часто добавляют к полиморфным объектам скрытые данные (так называемый указатель на виртуальную таблицу), которые определяют сущность объекта во время выполнения программы. В случае множественного наследования в объекте содержится несколько таких таблиц, с различными смещениями внутри объекта, и большинство реализаций добавляют дополнительные внутренние указатели при виртуальном наследовании. При обычном использовании компилятор принимает меры для корректного управления всеми скрытыми полями; применение memcpy способно внести в этот механизм только хаос.

Аналогично, функция memcmp — неподходящий инструмент для сравнения чего-то более сложного, чем просто наборы битов. Иногда эта функция делает слишком мало (например, сравнение строк в стиле С — не то же, что и сравнение указателей, при помощи которых эти строки реализованы). А иногда, как это ни парадоксально, memcmp делает слишком много (например, memcmp может совершенно напрасно сравнивать байты, которые не являются частью состояния объекта, такие как заполнители, вставленные компилятором для выравнивания). В обоих случаях результат сравнения оказывается неверным.


На Facebook В Твиттере В Instagram В Одноклассниках Мы Вконтакте
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!

Похожие книги на "Стандарты программирования на С++. 101 правило и рекомендация"

Книги похожие на "Стандарты программирования на С++. 101 правило и рекомендация" читать онлайн или скачать бесплатно полные версии.


Понравилась книга? Оставьте Ваш комментарий, поделитесь впечатлениями или расскажите друзьям

Все книги автора Герб Саттер

Герб Саттер - все книги автора в одном месте на сайте онлайн библиотеки LibFox.

Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Отзывы о "Герб Саттер - Стандарты программирования на С++. 101 правило и рекомендация"

Отзывы читателей о книге "Стандарты программирования на С++. 101 правило и рекомендация", комментарии и мнения людей о произведении.

А что Вы думаете о книге? Оставьте Ваш отзыв.