Читаем Стандарты программирования на С++ полностью

Пример. Рисование фигур. Классический пример — рисование различных объектов. Типичный подход в стиле С использует выбор типа. Для этого определяется член-перечисление id_, который хранит тип каждой фигуры — прямоугольник, окружность и т.д. Рисующий код выполняет необходимые действия в зависимости от выбранного типа:

class Shape { // ...

 enum { RECTANGLE, TRIANGLE, CIRCLE } id_;

 void Draw() const {

  switch (id_) { // плохой метод

  case RECTANGLE:

   // ... Код для прямоугольника …

   break;

  case TRIANGLE:

   // ... Код для треугольника …

   break;

  case CIRCLE:

   // ... Код для окружности …

   break;

  default: // Плохое решение

   assert(!"при добавлении нового типа надо "

           "обновить эту конструкцию" );

   break;

  }

 }

};

Такой код сгибается под собственным весом, он хрупок, ненадежен и сложен. В частности, он страдает транзитивной циклической зависимостью, о которой говорилось в рекомендации 22. Ветвь по умолчанию конструкции switch — четкий симптом синдрома "не знаю, что мне делать с этим типом". И все эти болезненные неприятности полностью исчезают, стоит только вспомнить, что С++ — объектно-ориентированный язык программирования:

class Shape { // ...

 virtual void Draw() const = 0; // Каждый производный

                                // класс реализует свою функцию

};

В качестве альтернативы (или в качестве дополнения) рассмотрим реализацию, которая следует совету по возможности принимать решения во время компиляции (см. рекомендацию 64):

template

void Draw(const S& shape) {

 shape.Draw(); // может быть виртуальной, а может и не быть

};             // См. рекомендацию 64

Теперь ответственность за рисование каждой геометрической фигуры переходит к реализации самой фигуры, и синдром "не знаю, что делать с этим типом" просто невозможен.

Ссылки

[Dewhurst03] §69, §96 • [Martin96c] • [Meyer00] • [Stroustrup00] §12.2.5 • [Sutter04] §36

<p>91. Работайте с типами, а не с представлениями</p>Резюме

Не пытайтесь делать какие-то предположения о том, как именно объекты представлены в памяти. Как именно следует записывать и считывать объекты из памяти — пусть решают типы объектов.

Обсуждение

Стандарт С++ дает очень мало гарантий по поводу представления типов в памяти.

• Целые числа используют двоичное представление.

• Для отрицательных чисел используется дополнительный код числа в двоичной системе.

• Обычные старые типы (Plain Old Data, POD[5]) имеют совместимое с С размещение в памяти: переменные-члены хранятся в порядке их объявления.

• Тип int занимает как минимум 16 битов.

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

• Размер int не равен ни 32 битам, ни какому-либо иному фиксированному размеру.

• Указатели и целые числа не всегда имеют один и тот же размер и не могут свободно преобразовываться друг в друга.

• Размещение класса в памяти не всегда приводит к размещению базового класса и членов в указанном порядке.

• Между членами класса (даже если они являются POD) могут быть промежутки в целях выравнивания.

• offsetof работает только для POD, но не для всех классов (хотя компилятор может и не сообщать об ошибках).

• Класс может иметь скрытые поля.

• Указатели могут быть совсем не похожи на целые числа. Если два указателя упорядочены и вы можете преобразовать их в целые числа, то получающиеся значения могут быть упорядочены иначе.

• Нельзя переносимо полагаться на конкретное размещение автоматических переменных в памяти или на направление роста стека.

• Указатели на функции могут иметь размер, отличный от размера указателя void*, несмотря на то, что некоторые API заставляют вас предположить, что их размеры одинаковы.

• Из-за вопросов выравнивания вы не можете записывать ни один объект по произвольному адресу в памяти.

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

Ссылки

[Dewhurst03] §95

<p>92. Избегайте <code>reinterpret_cast</code></p>Резюме
Перейти на страницу:

Все книги серии C++ In-Depth

Стандарты программирования на С++
Стандарты программирования на С++

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

Андрей Александреску , Герб Саттер

Программирование, программы, базы данных

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных