Макросы остаются единственно возможным решением для некоторых важных задач, таких как защита директивы #include (см. рекомендацию 24), использование директив #ifdef и #if defined для условной компиляции и реализация assert (см. рекомендацию 68).

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

Можно (но осторожно) использовать макросы вместо большого количества копирований и вставок близких фрагментов кода.

Заметим, что [C99] и [Boost] включают соответственно умеренные и радикальные расширения препроцессоров.

Ссылки

[Boost] • [С99] • [Dewhurst03] §25-28 • [Lakos96] §2.3.4 • [Meyers96] §1 • [Stroustrup94] §3.3.1 • [Stroustrup00] §1.6.1, §7.8 • [Sutter02] §34-35 • [Sutter04] §31 • [Sutter04a]

<p>17. Избегайте магических чисел</p>Резюме

Избегайте использования в коде литеральных констант наподобие 42 или 3.1415926. Такие константы не самоочевидны и усложняют сопровождение кода, поскольку вносят в него трудноопределимый вид дублирования. Используйте вместо них символьные имена и выражения наподобие width*aspectRatiо.

Обсуждение

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

Одно число 42 может не быть тем же числом 42, что и другое. Что еще хуже, программист может выполнять какие-то вычисления "в уме" (например: "Вот это 84 — просто удвоенное 42, которое было пятью строками ранее"), что совершенно запутывает код и делает последующую замену 42 другой константой источником огромного количества ошибок.

Лучше заменять такие жестко кодированные величины символьными константами. Строки лучше хранить отдельно от кода (например, в отдельном .срр-файле или файле ресурса), что позволит непрограммистам просмотреть и обновить их, снижая количество дубликатов и помогая в интернационализации вашей программы.

Примеры

Пример 1. Важные константы из предметной области на уровне пространств имен.

const size_t PAGE_SIZE = 8192,

             WORDS_PER_PAGE = PAGE_SIZE / sizeof(int),

             INFO_BITS_PER_PAGE = 32 * CHAR_BIT;

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

// Файл widget.h

class Widget {

 // Значение указано в объявлении

 static const int defaultWidth = 400;

 // Значение указано в определении

 static const double defaultPercent;

 static const char* Name() { return "widget"; }

};

// Файл widget.cpp

// Значение указано в определении

const double widget::defaultPercent = 66.67;

// Требуется объявление

const int widget::defaultWidth;

Ссылки

[Dewhurst03] §2 • [Kernighan99] §1.5 • [Stroustrup00] §4.8, §5.4

<p>18. Объявляйте переменные как можно локальнее</p>Резюме

Избегайте "раздувания" областей видимости. Переменных должно быть как можно меньше, а время их жизни — как можно короче. Эта рекомендация по сути является частным случаем рекомендации 10.

Обсуждение

Переменные, время жизни которых превышает необходимое, имеют ряд недостатков.

• Они делают программу трудно понимаемой и сопровождаемой. Например, должен ли код обновлять строку path на уровне модуля, если изменен только текущий диск?

• Они засоряют контекст своими именами. Непосредственным следствием является то, что переменные на уровне пространства имен, наиболее видимые среди всех остальных, одновременно являются и наихудшими (см. рекомендацию 10).

Перейти на страницу:

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

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