Чтение онлайн

на главную - закладки

Жанры

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

Александреску Андрей

Шрифт:

Функциональные объекты должны быть адаптируемы. Стандартные связыватели и адаптеры полагаются на наличие определенных инструкций

typedef
, обеспечить которые легче всего при наследовании ваших функциональных объектов от
unary_function
или
binary_function
. Инстанцируйте
unary_function
или
binary_function
с теми типами, которые получает и возвращает ваш оператор
operator
(при этом у каждого типа, не являющегося указателем, следует убрать все спецификаторы
const
верхнего
уровня, а также все
&
).

Постарайтесь избежать наличия нескольких операторов

operator
, поскольку это затрудняет адаптируемость. Дело в том, что обычно оказывается невозможно обеспечить корректные инструкции
typedef
, необходимые для адаптирования, поскольку один и тот же синоним типа, определяемый через инструкцию
typedef
, имеет разные значения для разных операторов
operator
.

Не все функциональные объекты являются предикатами — предикаты представляют собой подмножество функциональных объектов (см. рекомендацию 87).

Ссылки

[Allison98] §15, §C • [Austern99] §4, §8, §15 • [Gamma95] Bridge • [Josuttis99] §8.2.4 • [Koenig97] §21, §29 • [Meyers97] §34 • [Meyers01] §38, §40, §46 • [Musser01] §2.4, §8, §23 • [Sutter00] §26-30 • [Vandevoorde03] §22

Безопасность типов

Если вы лжете компилятору, он будет мстить.

— Генри Спенсер (Henry Spencer)

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

— Алан Перлис (Alan Perlis)

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

Основная идея поддержки корректности типов — всегда считывать информацию в том формате, в котором она была записана. Иногда С++ позволяет легко нарушить это правило; приведенные в этом разделе рекомендации помогут вам избежать подобных ошибок.

В этом разделе мы считаем наиболее значимой рекомендацию 91 — "Работайте с типами, а не с представлениями". Система типов — ваш друг и верный союзник. Воспользуйтесь ее помощью и попытайтесь не злоупотреблять ее доверием.

90. Избегайте явного выбора типов — используйте полиморфизм

Резюме

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

Обсуждение

Настройка поведения в зависимости от типа объекта с использованием инструкции выбора

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

В идеале добавление новых возможностей в программу должно осуществляться добавлением нового кода, а не изменением старого (см. рекомендацию 37). В реальной жизни это не всегда так — зачастую в дополнение к написанию нового кода мы вынуждены вносить изменения в уже имеющийся код. Такие изменения, однако, крайне нежелательны и должны быть минимизированы по двум причинам. Во-первых, изменения могут нарушить имеющуюся функциональность. Во-вторых, они препятствуют масштабируемости при росте системы и добавлении новых возможностей, поскольку количество "узлов поддержки", к которым надо возвращаться и вносить изменения, все время возрастает. Это наблюдение приводит к принципу Открытости-Закрытости, который гласит: любая сущность (например, класс или модуль) должна быть открыта для расширений, но закрыта для изменений (см. [Martin96c] и [Meyer00]).

Каким же образом мы можем написать код, который будет легко расширяем без внесения изменений? Используйте полиморфизм для написания кода в терминах абстракций (см. также рекомендацию 36), после чего при необходимости добавления функциональности это можно будет сделать путем разработки и добавления различных реализаций упомянутых абстракций. Шаблоны и виртуальные функции образуют барьер для зависимостей между кодом, использующим абстракции, и кодом, их реализующим (см. рекомендацию 64).

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

Совсем иначе обстоит дело с предельно детализированным кодом, который использует мало абстракций или вовсе обходится без них, работая исключительно с конкретными типами и их отдельными операциями. Добавление новой функциональности в такой код — сущее мучение.

Примеры

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

id_
, который хранит тип каждой фигуры — прямоугольник, окружность и т.д. Рисующий код выполняет необходимые действия в зависимости от выбранного типа:

class Shape { // ...

 enum { RECTANGLE, TRIANGLE, CIRCLE } id_;

 void Draw const {

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

case RECTANGLE:

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

break;

case TRIANGLE:

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

break;

case CIRCLE:

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

Поделиться:
Популярные книги

Черный маг императора 3

Герда Александр
3. Черный маг императора
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Черный маг императора 3

Повелитель механического легиона. Том VIII

Лисицин Евгений
8. Повелитель механического легиона
Фантастика:
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Повелитель механического легиона. Том VIII

Пипец Котенку! 3

Майерс Александр
3. РОС: Пипец Котенку!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Пипец Котенку! 3

Разбуди меня

Рам Янка
7. Серьёзные мальчики в форме
Любовные романы:
современные любовные романы
остросюжетные любовные романы
5.00
рейтинг книги
Разбуди меня

Боги, пиво и дурак. Том 6

Горина Юлия Николаевна
6. Боги, пиво и дурак
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Боги, пиво и дурак. Том 6

Болотник 2

Панченко Андрей Алексеевич
2. Болотник
Фантастика:
попаданцы
альтернативная история
6.25
рейтинг книги
Болотник 2

Ты всё ещё моя

Тодорова Елена
4. Под запретом
Любовные романы:
современные любовные романы
7.00
рейтинг книги
Ты всё ещё моя

S-T-I-K-S. Пройти через туман

Елисеев Алексей Станиславович
Вселенная S-T-I-K-S
Фантастика:
боевая фантастика
7.00
рейтинг книги
S-T-I-K-S. Пройти через туман

Имя нам Легион. Том 4

Дорничев Дмитрий
4. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 4

Сводный гад

Рам Янка
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Сводный гад

Я князь. Книга XVIII

Дрейк Сириус
18. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я князь. Книга XVIII

Королевская Академия Магии. Неестественный Отбор

Самсонова Наталья
Любовные романы:
любовно-фантастические романы
8.22
рейтинг книги
Королевская Академия Магии. Неестественный Отбор

Последняя Арена 6

Греков Сергей
6. Последняя Арена
Фантастика:
рпг
постапокалипсис
5.00
рейтинг книги
Последняя Арена 6

Жребий некроманта. Надежда рода

Решетов Евгений Валерьевич
1. Жребий некроманта
Фантастика:
фэнтези
попаданцы
6.50
рейтинг книги
Жребий некроманта. Надежда рода